P2.inf: refer update sites based on location - eclipse-rcp

I have developed an RCP application and I am providing p2 update functionality.
In my p2.inf i am providing the url for update site. I don't want user to add any site so I have disabled an option to add a site. My p2.inf looks like:
instructions.configure=\
addRepository(type:0,location:http${#58}//blrupdates.com/Updates);\
addRepository(type:1,location:http${#58}//blrupdates.com/Updates);
if user location is bangalore, RCP application should go to brlupdates.com, if user location is chennai then RCP application should look for update at chnupdates.com.
how to add another repository location in p2.inf?
-Priyank

You need to add the repository programatically. The following solution is taken from here. Another solution, that I'm not sure it would work is to use redirection. You define one p2 repository and then you redirect the user to the location based repository.
import org.eclipse.equinox.internal.p2.ui.model.MetadataRepositoryElement;
import org.eclipse.equinox.internal.p2.ui.model.ElementUtils;
#SuppressWarnings("restriction")
public class P2Util {
private static String UPDATE_SITE = "http://www.example.com/update_site";
public static void setRepositories() throws InvocationTargetException {
try {
final MetadataRepositoryElement element = new MetadataRepositoryElement(null, new URI(UPDATE_SITE), true);
ElementUtils.updateRepositoryUsingElements(new MetadataRepositoryElement[] {element}, null);
} catch (URISyntaxException e) {
e.printStackTrace();
throw new InvocationTargetException(e);
}
}
}

Related

Is it possible to access sonarqube analysis results in a plugin?

As per the sonar logs, I see that sonar first runs the sensors, then the decorators and then stores the analysis results to the database. Is is possible to access analysis results in a sonar plugin?
Thanks
The Sonar web application is available at localhost:9000 (or wherever it's installed).
There is also a plugin for Eclipse to view issues:
http://docs.codehaus.org/display/SONAR/SonarQube+in+Eclipse
I finally found a solution to my problem here.
http://sonarqube.15.x6.nabble.com/sonar-dev-Where-can-I-find-new-issue-information-on-sonar-db-td5021022.html
// this annotation is important to be sure that relevant data on issues are up-to-date.
#DependsUpon(DecoratorBarriers.ISSUES_TRACKED)
public final class MyDecorator implements Decorator {
private final ResourcePerspectives perspectives;
public TechnicalDebtDecorator(ResourcePerspectives perspectives) {
this.perspectives = perspectives;
}
public void decorate(Resource resource, DecoratorContext context) {
Issuable issuable = perspectives.as(Issuable.class, resource);
if (issuable != null) {
List<Issue> issues = issuable.issues();
// Issue has method isNew()
}
}
}

How to restrict a component to add only once per page

How to restrict a CQ5/Custom component to add only once per page.? I want to restrict the drag and drop of component into the page when the author is going to add the same component for the second time into the same page.
One option is to include the component directly in the JSP of the template and exclude it from the list of available components in the sidekick. To do so, add the component directly to your JSP (foundation carousel in this example):
<cq:include path="carousel" resourceType="foundation/components/carousel" />
To hide the component from the sidekick, either set:
componentGroup: .hidden
or exclude it from the list of "Allowed Components" using design mode.
If you need to allow users to create a page without this component you can provide a second template with the cq:include omitted.
Thanks Rampant, I have followed your method and link stated.
Posting link again : please follow this blog
It was really helpful. I am posting the implementation whatever I have done.
It worked fine for me. One can definitely improve the code quality, this is raw code and is just for reference.
1.Servlet Filter
Keep this in mind that,if any resource gets refereshed, this filter will execute. So you need to filter the contents at your end for further processing.
P.S. chain.doFilter(request,response); is must. or cq will get hanged and nothing will be displayed.
#SlingFilter(generateComponent = false, generateService = true, order = -700,
scope = SlingFilterScope.REQUEST)
#Component(immediate = true, metatype = false)
public class ComponentRestrictorFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {}
#Reference
private ResourceResolverFactory resolverFactory;
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
WCMMode mode = WCMMode.fromRequest(request);
if (mode == WCMMode.EDIT) {
SlingHttpServletRequest slingRequest = (SlingHttpServletRequest) request;
PageManager pageManager = slingRequest.getResource().getResourceResolver().adaptTo(PageManager.class);
Page currentPage = pageManager.getContainingPage(slingRequest.getResource());
logger.error("***mode" + mode);
if (currentPage != null )) {
ComponentRestrictor restrictor = new ComponentRestrictor(currentPage.getPath(), RESTRICTED_COMPONENT);
restrictor.removeDuplicateEntry(resolverFactory,pageManager);
}
chain.doFilter(request, response);
}
}
public void destroy() {}
}
2.ComponentRestrictor class
public class ComponentRestrictor {
private String targetPage;
private String component;
private Pattern pattern;
private Set<Resource> duplicateResource = new HashSet<Resource>();
private Logger logger = LoggerFactory.getLogger(ComponentRestrictor.class);
private Resource resource = null;
private ResourceResolver resourceResolver = null;
private ComponentRestrictorHelper helper = new ComponentRestrictorHelper();
public ComponentRestrictor(String targetPage_, String component_){
targetPage = targetPage_ + "/jcr:content";
component = component_;
}
public void removeDuplicateEntry(ResourceResolverFactory resolverFactory, PageManager pageManager) {
pattern = Pattern.compile("([\"']|^)(" + component + ")(\\S|$)");
findReference(resolverFactory, pageManager);
}
private void findReference(ResourceResolverFactory resolverFactory, PageManager pageManager) {
try {
resourceResolver = resolverFactory.getAdministrativeResourceResolver(null);
resource = resourceResolver.getResource(this.targetPage);
if (resource == null)
return;
search(resource);
helper.removeDuplicateResource(pageManager,duplicateResource);
} catch (LoginException e) {
logger.error("Exception while getting the ResourceResolver " + e.getMessage());
}
resourceResolver.close();
}
private void search(Resource parentResource) {
searchReferencesInContent(parentResource);
for (Iterator<Resource> iter = parentResource.listChildren(); iter.hasNext();) {
Resource child = iter.next();
search(child);
}
}
private void searchReferencesInContent(Resource resource) {
ValueMap map = ResourceUtil.getValueMap(resource);
for (String key : map.keySet()) {
if (!helper.checkKey(key)) {
continue;
}
String[] values = map.get(key, new String[0]);
for (String value : values) {
if (pattern.matcher(value).find()) {
logger.error("resource**" + resource.getPath());
duplicateResource.add(resource);
}
}
}
}
}
3.To remove the node/ resource
Whichever resource you want to remove/delete just use PageManager api
pageManeger.delete(resource,false);
That's it !!! You are good to go.
None of the options looks easy to implement. The best approach I found is to use the ACS Commons Implementation which is very easy and can be adopted into any project.
Here is the link and how to configure it:
https://github.com/Adobe-Consulting-Services/acs-aem-commons/pull/639
Enjoy coding !!!
you can't prevent that without doing some massive hacking to the ui code, and even then, you've only prevented it from one aspect of the ui. there's still crxde, and then the ability to POST content.
if this is truly a requirement, the best approach might be the following:
have the component check for a special value in the pageContext object (use REQUEST_SCOPE)
if value is not found, render component and set value
otherwise, print out a message that component can only be used once
note that you can't prevent a dialog from showing, but at the very least the author has an indication that that particular component can only be used once.
It sounds like there needs to be clarification of requirements (and understanding why).
If the authors can be trained, let them manage limits of components through authoring and review workflows.
If there is just 1 fixed location the component can appear, then the page component should include the content component, and let the component have an "enable" toggle property to determine if it should render anything. The component's group should be .hidden to prevent dragging from the sidekick.
If there is a fixed set of locations for the component, the page component can have a dropdown of the list of locations (including "none"). The page render component would then conditionally include the component in the correct location. Again, prevent dragging the component from the sidekick.
In the "hard to imagine" case that the component can appear anywhere on the page, added by authors, but limited to only 1 instance - use a wrapper component to manage including the (undraggable) component. Let the authors drag the wrapper on the page as many times as they want, but the wrapper should query the page's resources and determine if it is the first instance, and if so, include the end component. Otherwise, the wrapper does nothing.
In our experience (>2years on CQ), implementing this type of business rules via code creates a brittle solution. Also, requirements have a habit of changing. If enforced via code, development work is required instead of letting authors make changes faster & elegantly.
None of these options are that great. If you truly want a robust solution to this problem (limit the number of items on the page without hardcoding location) then the best way is with a servlet filter chain OSGI service where you can administer the number of instances and then use a resource resolver to remove offending instances.
The basic gist is:
Refresh the page on edit using cq:editConfig
Create an OSGI service implementing javax.servlet.Filter that encapsulates your business rules.
Use the filter to remove excess components according to business rules
Continue page processing.
For more details see here:
Using a servlet filter to limit the number of instances of a component per page or parsys
This approach will let you administer the number of items per page or per parsys and apply other possibly complex business rules in a way that the other offered solutions simply cannot.

Facebook with DotNetOpenAuth 4.1.0.12182

I'm attempting to create a user login for Facebook and Windows LiveId using DotNetOpenAuth 4.1.0.12182
However the examples in the download make use of DotNetOpenAuth.ApplicationBlock and DotNetOpenAuth.ApplicationBlock.Facebook which don't exist in the current build.
Instead there is the DotNetOpenAuth.AspNet.Clients namespace which includes FacebookClient and WindowsLiveClient - however I can't find any example of how to use these.
Do any examples or documentation exist?
I have been able to get DNOA version 4.1.0.12182, .Net 3.5 and Facebook to work with each other by creating a FacebookAuthClient that is derived off of the DotNetOpenAuth.OAuth2.WebServerClient. One little gotcha that I have found is that if you are using cookie based sessions then you have to access the session before you use the OAuth functionality. From what I can tell this is because DNOA uses the Session ID as the state parameter and if session has never been accessed it can change between requests. This will cause a state parameter mismatch error when the response comes back from Facebook.
FacebookAuthClient:
public class FacebookAuthClient : DotNetOpenAuth.OAuth2.WebServerClient
{
private static readonly DotNetOpenAuth.OAuth2.AuthorizationServerDescription Description = new DotNetOpenAuth.OAuth2.AuthorizationServerDescription
{
TokenEndpoint = new Uri("https://graph.facebook.com/oauth/access_token"),
AuthorzationEndpoint = new Uri("https://graph.facebook.com/oauth/authorize")
};
public static readonly string [] ScopeNeeded = { "publish_stream" };
public FacebookAuthClient()
: base(Description)
{
}
}
Facebook.aspx.cs:
public partial class FacebookPage : System.Web.UI.Page
{
private FacebookAuthClient _client = new FacebookAuthClient
{
ClientIdentifier = ConfigurationManager.AppSettings["FBClientId"], //The FB app's Id
ClientCredentialApplicator = DotNetOpenAuth.OAuth2.ClientCredentialApplicator.PostParameter(ConfigurationManager.AppSettings["FBClientSecret"]) // The FB app's secret
}
protected void Page_Load(object sender, EventArgs e)
{
DotNetOpenAuth.OAuth2.IAuthorizationState auth = _client.ProcessUserAuthorization();
if (_auth == null)
{
// Kick off authorization request with the required scope info
client.RequestUserAuthorization(FacebookAuthClient.ScopeNeeded);
}
}
}
This is just a test app so there is no error handling but it seems to work.
Edit
I used the DotNetOpenAuth(unified) NuGet package for all of this.
Edit
Added missing .PostParameter call to the creating of the ClientCredentialApplicator.
You'll need to use ctp version 3.5 of DNOA. Version 4+ has been made to work with a later draft of OAuth 2 then Facebook uses.
You can find it on the owners GitHub:
https://github.com/AArnott/dotnetopenid

How to programmatically new a java class which implements sepecified interface in eclipse plugin development

Friends,
Now we are developing a eclipse plugin, it contains a action to generated a service interface and it's impl stub.
Now the interface is generated, I want to use eclipse JDT to create a java class which implements sepecified interface, but don't know how.
The info we have:
the interface name, the impl class name, the packagename, the java project contains them.
Thanks in advance for your kindly help.
A quick scan of how the new class wizard does it, it seems that there is no public easy to use API for this. You can have a look at org.eclipse.jdt.ui.wizards.NewTypeWizardPage.createType(IProgressMonitor) method to see how JDT itself creates new classes.
It should be possible to extend the org.eclipse.jdt.ui.wizards.NewTypeWizardPage, so you can leverage the createType() method.
Probably the minimal steps you would have to do is simply generate source content into the correctly placed IFile. ex:
public Object execute(ExecutionEvent event) throws ExecutionException {
final String PACKAGE_PATH = "z.ex/src/z/ex/go";
final String CONTENT = "package z.ex.go;\n"
+ "public class RunAway {\npublic static void main(String[] args) {\n"
+ "System.out.println(\"Run Away\");\n}\n}\n";
final IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
final IResource packageResource = root.findMember(PACKAGE_PATH);
if (packageResource instanceof IFolder) {
IFolder packageFolder = (IFolder) packageResource;
final IFile file = packageFolder.getFile("RunAway.java");
try {
if (!file.exists()) {
file.create(new ByteArrayInputStream(CONTENT.getBytes()),
true, new NullProgressMonitor());
} else {
file.setContents(
new ByteArrayInputStream(CONTENT.getBytes()),
IFile.FORCE | IFile.KEEP_HISTORY,
new NullProgressMonitor());
}
} catch (CoreException e) {
e.printStackTrace();
}
}
return null;
}
See AbstractNewClassWizard for a smaller example that is similar to NewTypeWizardPage and uses some of the JDT APIs.
You can use the new class wizard to create classes.
This will prompt the user for the class name, et cetera. You can initialize the values of the wizard page. Below I am setting the source folder only (and tell the wizard that it cannot be changed, thus the second false parameter). You might want to set the interface and possible the package as well.
OpenNewClassWizardAction wizard = new OpenNewClassWizardAction();
wizard.setOpenEditorOnFinish(false);
NewClassWizardPage page = new NewClassWizardPage();
page.setPackageFragmentRoot(sourceFolder, false);
wizard.setConfiguredWizardPage(page);
wizard.run();
return (IType) wizard.getCreatedElement();
Hope that helps!
Create the entire java file using the JDT - AST. First create the AST and then write it to a java file. It might look as hefty work, but its the best one. You will have complete control.

How can I use properties taken from a file in the code of an eclipse PDE fragment/plugin project?

I have created an eclipse plugin project and a corresponding fragment project which I use for junit tests.
In the fragment I specify the plugin project as the "Host plugin". Further I specify the following on the build.properties pane:
source.. = src/
output.. = bin/
bin.includes = META-INF/,\
.,\
my.properties
where my.properties is a file located at the root of the fragment project. I have then written a test where I try to load the my.properties file like this:
Properties properties = new Properties();
InputStream istream = this.getClass().getClassLoader()
.getResourceAsStream("my.properties");
try {
properties.load(istream);
} catch (IOException e) {
e.printStackTrace();
}
but istream is null and the test fails with a NullPointerException when calling load in the try block.
I have tried to do the same thing in the host plugin and there it works fine. Any ideas about why I can't read resouces in my PDE fragment when using Junit?
Try using Bundle#getEntry. If your plug-in has an Activator, you get a BundleContext object when your plugin is started (use Bundle-ActivationPolicy: lazy in your manifest). You can get the Bundle object from the BundleContext:
public class Activator implements BundleActivator {
private static Bundle bundle;
public static Bundle getBundle() {
return myBundle;
}
public void start(BundleContext context) throws Exception {
bundle = context.getBundle();
}
}
...
URL url = Activator.getBundle().getEntry("my.properties");
InputStream stream = url.openStream();
properties.load(stream);
One problem you MIGHT be having is that
InputStream istream = this.getClass().getClassLoader().
getResourceAsStream("my.properties");
behaves differently in two situations where "this" is located in a different package. Since you did not append "/" to the beginning, java will automatically start looking at the package root instead of the classpath root for the resource. If the code in your plug-in project and your fragment project exist in different packages, you have a problem.
Andrew Niefer has pointed the direction, but the solution is wrong. That is one that works:
1) Add super(); to the your Activator constructor.
2) Put this into the constructor of your plugin:
Properties properties = new Properties();
try {
Bundle bundle=Activator.getDefault().getBundle();
URL url = bundle.getEntry("plugin.properties");
InputStream stream;
stream = url.openStream();
properties.load(stream);
} catch (Exception e) {
e.printStackTrace();
}
And you have functioning "properties".
Explanations:
Doing (1) you will reach all that functionality:
public class Activator implements BundleActivator {
private static Bundle bundle;
public static Bundle getBundle() {
return myBundle;
}
public void start(BundleContext context) throws Exception {
bundle = context.getBundle();
}
}
It is present already in the pre-parent class Plugin. And you simply can't put it into Activator, because getBundle() is final in Plugin.
Notice Activator.getDefault() in (2). Without it bundle is unreachable, it is not static. And if you simply create a new instance of activator, bundle of it will be null.
There is one more way to take a bundle:
Bundle bundle = Platform.getBundle(Activator.PLUGIN_ID);
Only check that Activator.PLUGIN_ID is set to the correct string - as is in the ID field of the Overview page of the plugin. BTW, you should check this Activator.PLUGIN_ID after every change of the plugin ID anyway.