blob: 16bb02a02bbb934a9e81778ff08e4ef786bf48d5 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.maven.apisupport;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import javax.swing.AbstractAction;
import javax.swing.Action;
import org.apache.maven.project.MavenProject;
import org.netbeans.api.project.Project;
import org.netbeans.modules.apisupport.project.api.BrandingUtils;
import org.netbeans.modules.apisupport.project.api.ManifestManager;
import org.netbeans.modules.apisupport.project.spi.BrandingModel;
import org.netbeans.modules.apisupport.project.spi.BrandingSupport;
import org.netbeans.modules.apisupport.project.spi.PlatformJarProvider;
import org.netbeans.modules.maven.api.FileUtilities;
import org.netbeans.modules.maven.api.NbMavenProject;
import static org.netbeans.modules.maven.apisupport.Bundle.*;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.awt.ActionRegistration;
import org.openide.awt.DynamicMenuContent;
import org.openide.filesystems.FileUtil;
import org.openide.util.ContextAwareAction;
import org.openide.util.EditableProperties;
import org.openide.util.Exceptions;
import org.openide.util.Lookup;
import org.openide.util.NbBundle.Messages;
import org.openide.util.RequestProcessor;
import org.openide.util.Utilities;
/**
* Opens branding editor window for 'branding' sub-project of a Maven app suite.
*
* @author S. Aubrecht
*/
@ActionID(id = "org.netbeans.modules.maven.apisupport.OpenBrandingEditorAction", category = "Project")
@ActionRegistration(displayName = "#LBL_OpenBrandingEditor", lazy=false)
@ActionReference(position = 3150, path = "Projects/org-netbeans-modules-maven/Actions")
@Messages("LBL_OpenBrandingEditor=Branding...")
public class OpenBrandingEditorAction extends AbstractAction implements ContextAwareAction {
private final Lookup context;
private static final RequestProcessor RP = new RequestProcessor(OpenBrandingEditorAction.class);
public OpenBrandingEditorAction() {
this( Lookup.EMPTY );
}
private OpenBrandingEditorAction( Lookup context ) {
super(LBL_OpenBrandingEditor());
putValue(DynamicMenuContent.HIDE_WHEN_DISABLED, true);
this.context = context;
}
@Override
@Messages("OpenBrandingEditorAction_Error_NoApplication=We could not find the application project that is associated with this branding project.\nPlease open it and retry.")
public void actionPerformed(ActionEvent e) {
RP.post(new Runnable() {
@Override public void run() {
final Project project = context.lookup(Project.class);
final MavenProject mavenProject = project.getLookup().lookup(NbMavenProject.class).getMavenProject();
final BrandingModel model = createBrandingModel(project, brandingPath(project));
final boolean hasAppProject = MavenNbModuleImpl.findAppProject(project) != null;
final boolean hasExternalPlatform = MavenNbModuleImpl.findIDEInstallation(project) != null;
EventQueue.invokeLater(new Runnable() {
@Override public void run() {
if (!hasAppProject && !hasExternalPlatform) {
//TODO do we need the external platform check? MavenPLatfomrJarProvider has it, but it's more generic than branding
NotifyDescriptor.Message message = new NotifyDescriptor.Message(OpenBrandingEditorAction_Error_NoApplication(), NotifyDescriptor.ERROR_MESSAGE);
DialogDisplayer.getDefault().notify(message);
return;
}
BrandingUtils.openBrandingEditor(mavenProject.getName(), project, model);
}
});
}
});
}
@Override
public Action createContextAwareInstance(Lookup actionContext) {
return new OpenBrandingEditorAction(actionContext);
}
public @Override boolean isEnabled() {
Project project = context.lookup(Project.class);
if (project == null) {
return false;
}
NbMavenProject mproject = project.getLookup().lookup(NbMavenProject.class);
if (mproject == null) {
return false;
}
return project.getProjectDirectory().getFileObject(brandingPath(project)) != null;
}
private String brandingPath(Project mavenProject) {
String brandingPath = PluginBackwardPropertyUtils.getPluginProperty(mavenProject, "brandingSources", "branding", null); //NOI18N
if(brandingPath != null) {
return FileUtilities.getRelativePath(FileUtil.toFile(mavenProject.getProjectDirectory()),
FileUtilities.resolveFilePath(FileUtil.toFile(mavenProject.getProjectDirectory()), brandingPath));
}
return "src/main/nbm-branding";
}
/**
* Creates a basic branding model.
* @param p Project to be branded.
* @param brandingPath Path relative to project's directory where branded are stored in.
*/
private static BrandingModel createBrandingModel(final Project p, final String brandingPath) {
BrandingModel model = new BrandingModel() {
@Override public Project getProject() {
return p;
}
@Override protected File getProjectDirectoryFile() {
return FileUtil.toFile(p.getProjectDirectory());
}
@Override protected BrandingSupport createBranding() throws IOException {
return new GenericBrandingSupport(p, brandingPath, this.locale = Locale.getDefault());
}
@Override protected boolean isBrandingEnabledRefresh() {
return true;
}
@Override protected String loadName() {
return null;
}
@Override protected String loadTitle() {
return null;
}
@Override
public void updateProjectInternationalizationLocales() {
}
};
model.init();
return model;
}
private static class GenericBrandingSupport extends BrandingSupport {
private final Project p;
private Map<String,BrandableModuleImpl> modules;
GenericBrandingSupport(Project p, String brandingPath, Locale locale) throws IOException {
super(p, brandingPath);
this.p = p;
this.locale = locale;
}
@Override protected BrandableModule findBrandableModule(String moduleCodeNameBase) {
return modules.get(moduleCodeNameBase);
}
@Override public Set<File> getBrandableJars() {
Set<File> jars = new HashSet<File>();
for (BrandableModuleImpl m : modules.values()) {
jars.add(m.jar);
}
return jars;
}
@Override protected Set<BrandableModule> loadModules() throws IOException {
if (modules != null) {
// XXX is there some way to tell that the effective platform has changed for e.g. a Maven module?
return null;
}
modules = new HashMap<String,BrandableModuleImpl>();
PlatformJarProvider pjp = p.getLookup().lookup(PlatformJarProvider.class);
if (pjp != null) {
for (File jar : pjp.getPlatformJars()) {
ManifestManager mfm = ManifestManager.getInstanceFromJAR(jar);
String cnb = mfm.getCodeNameBase();
if (cnb != null) {
modules.put(cnb, new BrandableModuleImpl(cnb, jar));
}
}
}
return new HashSet<BrandableModule>(modules.values());
}
@Override protected Map<String,String> localizingBundle(BrandableModule moduleEntry) {
File jar = ((BrandableModuleImpl) moduleEntry).jar;
ManifestManager mfm = ManifestManager.getInstanceFromJAR(jar);
String localizingBundle = mfm.getLocalizingBundle();
if (localizingBundle == null) {
return Collections.emptyMap();
}
EditableProperties props = new EditableProperties(false);
try {
InputStream is = new URL("jar:" + Utilities.toURI(jar) + "!/" + localizingBundle).openStream();
try {
props.load(is);
} finally {
is.close();
}
} catch (IOException x) {
Exceptions.printStackTrace(x);
}
return props;
}
private static class BrandableModuleImpl implements BrandableModule {
private final String cnb;
private final File jar;
BrandableModuleImpl(String cnb, File jar) {
this.cnb = cnb;
this.jar = jar;
}
@Override public String getCodeNameBase() {
return cnb;
}
@Override public File getJarLocation() {
return jar;
}
@Override public boolean equals(Object obj) {
if (!(obj instanceof BrandableModuleImpl)) {
return false;
}
BrandableModuleImpl o = (BrandableModuleImpl) obj;
return cnb.equals(o.cnb) && jar.equals(o.jar);
}
@Override public int hashCode() {
return cnb.hashCode();
}
@Override public String toString() {
return cnb;
}
@Override public String getRelativePath() {
String base;
if (cnb.equals("org.netbeans.bootstrap")) {
base = "boot";
} else if (cnb.equals("org.netbeans.core.startup")) {
base = "core";
} else {
base = cnb.replace('.', '-');
}
String dir;
if (cnb.matches("org[.](netbeans[.]bootstrap|openide[.](modules|util(|[.]lookup)))")) {
dir = "lib";
} else if (cnb.matches("org[.](netbeans[.]core[.]startup|openide[.]filesystems)")) {
dir = "core";
} else {
dir = "modules";
}
return dir + '/' + base + ".jar";
}
}
}
}