/* * Copyright (c) 2007-2009, Osmorc Development Team * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this list * of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or other * materials provided with the distribution. * * Neither the name of 'Osmorc Development Team' nor the names of its contributors may be * used to endorse or promote products derived from this software without specific * prior written permission. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.osmorc.facet.ui; import com.intellij.facet.ui.FacetEditorContext; import com.intellij.facet.ui.FacetEditorTab; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.fileChooser.FileChooser; import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleServiceManager; import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.ui.TextFieldWithBrowseButton; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.*; import com.intellij.ui.UserActivityListener; import com.intellij.ui.UserActivityWatcher; import org.jetbrains.annotations.Nls; import org.osgi.framework.Constants; import org.osgi.framework.Version; import org.osmorc.facet.OsmorcFacetConfiguration; import org.osmorc.settings.MyErrorText; import org.osmorc.settings.ProjectSettings; import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.io.IOException; import java.util.jar.Attributes; /** * The facet editor tab which is used to set up general Osmorc facet settings. * * @author <a href="mailto:janthomae@janthomae.de">Jan Thomä</a> * @author Robert F. Beeger (robert@beeger.net) */ public class OsmorcFacetGeneralEditorTab extends FacetEditorTab { public OsmorcFacetGeneralEditorTab(FacetEditorContext editorContext) { _editorContext = editorContext; _module = editorContext.getModule(); _manifestFileChooser.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { onManifestFileSelect(); } }); _bndFile.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { selectBuildFile(_bndFile); } }); _bundlorFile.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { selectBuildFile(_bundlorFile); } }); ChangeListener listener = new ChangeListener() { public void stateChanged(ChangeEvent e) { updateGui(); } }; _manuallyEditedRadioButton.addChangeListener(listener); _useBndFileRadioButton.addChangeListener(listener); _useBundlorFileRadioButton.addChangeListener(listener); _controlledByOsmorcRadioButton.addChangeListener(listener); UserActivityWatcher watcher = new UserActivityWatcher(); watcher.addUserActivityListener(new UserActivityListener() { public void stateChanged() { _modified = true; checkFileExisting(); } }); watcher.register(_root); _useProjectDefaultManifestFileLocation.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { onUseProjectDefaultManifestFileLocationChanged(); } }); _createButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { tryCreateBundleManifest(); checkFileExisting(); } }); } private void updateGui() { boolean isBnd = _useBndFileRadioButton.isSelected(); boolean isBundlor = _useBundlorFileRadioButton.isSelected(); boolean isManuallyEdited = _manuallyEditedRadioButton.isSelected(); _editorContext.putUserData(MANUAL_MANIFEST_EDITING_KEY, isManuallyEdited); _editorContext.putUserData(BND_CREATION_KEY, isBnd); _editorContext.putUserData(BUNDLOR_CREATION_KEY, isBundlor); _bndPanel.setEnabled(isBnd); _bundlorPanel.setEnabled(isBundlor); _manifestPanel.setEnabled(isManuallyEdited); _useProjectDefaultManifestFileLocation.setEnabled(isManuallyEdited); _useModuleSpecificManifestFileLocation.setEnabled(isManuallyEdited); _manifestFileChooser.setEnabled(isManuallyEdited && !_useProjectDefaultManifestFileLocation.isSelected()); _bndFile.setEnabled(isBnd); _bundlorFile.setEnabled(isBundlor); checkFileExisting(); } private void onUseProjectDefaultManifestFileLocationChanged() { _manifestFileChooser.setEnabled(!_useProjectDefaultManifestFileLocation.isSelected()); _modified = true; } private void onManifestFileSelect() { VirtualFile[] roots = getContentRoots(_module); VirtualFile currentFile = findFileInContentRoots(_manifestFileChooser.getText(), _module); VirtualFile manifestFileLocation = FileChooser.chooseFile(_editorContext.getProject(), FileChooserDescriptorFactory.createSingleFileOrFolderDescriptor(), currentFile); if (manifestFileLocation != null) { for (VirtualFile root : roots) { String relativePath = VfsUtilCore.getRelativePath(manifestFileLocation, root, File.separatorChar); if (relativePath != null) { // okay, it resides inside one of our content roots, so far so good. if (manifestFileLocation.isDirectory()) { // its a folder, so add "MANIFEST.MF" to it as a default. relativePath += "/MANIFEST.MF"; } _manifestFileChooser.setText(relativePath); break; } } } } private static VirtualFile[] getContentRoots(Module module) { return ModuleRootManager.getInstance(module).getContentRoots(); } @Nls public String getDisplayName() { return "General"; } public JComponent createComponent() { return _root; } public boolean isModified() { return _modified; } private void selectBuildFile(TextFieldWithBrowseButton field) { VirtualFile[] roots = getContentRoots(_module); VirtualFile currentFile = findFileInContentRoots(field.getText(), _module); VirtualFile fileLocation = FileChooser.chooseFile(_editorContext.getProject(), FileChooserDescriptorFactory.createSingleFileNoJarsDescriptor(), currentFile); if (fileLocation != null) { for (VirtualFile root : roots) { String relativePath = VfsUtilCore .getRelativePath(fileLocation, root, File.separatorChar); if (relativePath != null) { field.setText(relativePath); break; } } } updateGui(); } public void apply() { OsmorcFacetConfiguration configuration = (OsmorcFacetConfiguration) _editorContext.getFacet().getConfiguration(); configuration.setOsmorcControlsManifest(_controlledByOsmorcRadioButton.isSelected()); configuration.setManifestLocation(_manifestFileChooser.getText()); configuration.setUseProjectDefaultManifestFileLocation(_useProjectDefaultManifestFileLocation.isSelected()); configuration.setUseBndFile(_useBndFileRadioButton.isSelected()); configuration.setUseBundlorFile(_useBundlorFileRadioButton.isSelected()); String bndFileLocation = _bndFile.getText(); bndFileLocation = bndFileLocation.replace('\\', '/'); configuration.setBndFileLocation(bndFileLocation); String bundlorFileLocation = _bundlorFile.getText(); bundlorFileLocation = bundlorFileLocation.replace('\\', '/'); configuration.setBundlorFileLocation(bundlorFileLocation); } public void reset() { OsmorcFacetConfiguration configuration = (OsmorcFacetConfiguration) _editorContext.getFacet().getConfiguration(); if (configuration.isUseBndFile()) { _useBndFileRadioButton.setSelected(true); } else if (configuration.isUseBundlorFile()) { _useBundlorFileRadioButton.setSelected(true); } else if (configuration.isOsmorcControlsManifest()) { _controlledByOsmorcRadioButton.setSelected(true); } else { _manuallyEditedRadioButton.setSelected(true); } _manifestFileChooser.setText(configuration.getManifestLocation()); if (configuration.isUseProjectDefaultManifestFileLocation()) { _useProjectDefaultManifestFileLocation.setSelected(true); } else { _useModuleSpecificManifestFileLocation.setSelected(true); } _bndFile.setText(configuration.getBndFileLocation()); _bundlorFile.setText(configuration.getBundlorFileLocation()); updateGui(); } @Override public void onTabEntering() { super.onTabEntering(); updateGui(); } public void disposeUIResources() { } private String getManifestLocation() { if (_controlledByOsmorcRadioButton.isSelected() || _useBndFileRadioButton.isSelected() || _useBundlorFileRadioButton.isSelected()) { return null; } if (_useModuleSpecificManifestFileLocation.isSelected()) { return _manifestFileChooser.getText(); } if (_useProjectDefaultManifestFileLocation.isSelected()) { final ProjectSettings projectSettings = ModuleServiceManager.getService(_module, ProjectSettings.class); return projectSettings.getDefaultManifestFileLocation(); } return null; } private void checkFileExisting() { boolean showWarning; if (_controlledByOsmorcRadioButton.isSelected() || _useBndFileRadioButton.isSelected()|| _useBundlorFileRadioButton.isSelected() ) { showWarning = false; } else { String location = getManifestLocation(); if (location == null) { showWarning = false; } else { VirtualFile file = findFileInContentRoots(location, _module); showWarning = file == null; } } _warningPanel.setVisible(showWarning); _root.revalidate(); } private void createUIComponents() { _errorText = new MyErrorText(); _errorText.setError("The manifest file does not exist."); } private void tryCreateBundleManifest() { // check if a manifest path has been set up final String manifestPath = getManifestLocation(); if (StringUtil.isEmpty(manifestPath)) { return; } final VirtualFile[] contentRoots = getContentRoots(_module); if (contentRoots.length > 0) { Application application = ApplicationManager.getApplication(); application.runWriteAction(new Runnable() { public void run() { try { VirtualFile contentRoot = contentRoots[0]; String completePath = contentRoot.getPath() + File.separator + manifestPath; // unify file separators completePath = completePath.replace('\\', '/'); // strip off the last part (its the filename) int lastPathSep = completePath.lastIndexOf('/'); String path = completePath.substring(0, lastPathSep); String filename = completePath.substring(lastPathSep + 1); // make sure the folders exist VfsUtil.createDirectories(path); // and get the virtual file for it VirtualFile parentFolder = LocalFileSystem.getInstance().refreshAndFindFileByPath(path); // some heuristics for bundle name and version String bundleName = _module.getName(); Version bundleVersion = null; int nextDotPos = bundleName.indexOf('.'); while (bundleVersion == null && nextDotPos >= 0) { try { bundleVersion = new Version(bundleName.substring(nextDotPos + 1)); bundleName = bundleName.substring(0, nextDotPos); } catch (IllegalArgumentException e) { // Retry after next dot. } nextDotPos = bundleName.indexOf('.', nextDotPos + 1); } VirtualFile manifest = parentFolder.createChildData(this, filename); String text = Attributes.Name.MANIFEST_VERSION + ": 1.0.0\n" + Constants.BUNDLE_MANIFESTVERSION + ": 2\n" + Constants.BUNDLE_NAME + ": " + bundleName + "\n" + Constants.BUNDLE_SYMBOLICNAME + ": " + bundleName + "\n" + Constants.BUNDLE_VERSION + ": " + (bundleVersion != null ? bundleVersion.toString() : "1.0.0") + "\n"; VfsUtil.saveText(manifest, text); } catch (IOException e) { throw new RuntimeException(e); } } }); VirtualFileManager.getInstance().refresh(false); } } @Override public String getHelpTopic() { return "reference.settings.module.facet.osgi"; } private static VirtualFile findFileInContentRoots(String fileName, Module module) { VirtualFile[] roots = getContentRoots(module); VirtualFile currentFile = null; for (VirtualFile root : roots) { currentFile = VfsUtil.findRelativeFile(fileName, root); if (currentFile != null) { break; } } return currentFile; } private JRadioButton _manuallyEditedRadioButton; private JRadioButton _controlledByOsmorcRadioButton; private TextFieldWithBrowseButton _manifestFileChooser; private JPanel _root; private JRadioButton _useProjectDefaultManifestFileLocation; private JRadioButton _useModuleSpecificManifestFileLocation; private JRadioButton _useBndFileRadioButton; private JPanel _manifestPanel; private TextFieldWithBrowseButton _bndFile; private JPanel _bndPanel; private JPanel _warningPanel; private JButton _createButton; private MyErrorText _errorText; private JRadioButton _useBundlorFileRadioButton; private TextFieldWithBrowseButton _bundlorFile; private JPanel _bundlorPanel; private boolean _modified; private final FacetEditorContext _editorContext; private final Module _module; static final Key<Boolean> MANUAL_MANIFEST_EDITING_KEY = Key.create("MANUAL_MANIFEST_EDITING"); static final Key<Boolean> BND_CREATION_KEY = Key.create("BND_CREATION"); static final Key<Boolean> BUNDLOR_CREATION_KEY = Key.create("BUNDLOR_CREATION"); }