001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU General
007: * Public License Version 2 only ("GPL") or the Common Development and Distribution
008: * License("CDDL") (collectively, the "License"). You may not use this file except in
009: * compliance with the License. You can obtain a copy of the License at
010: * http://www.netbeans.org/cddl-gplv2.html or nbbuild/licenses/CDDL-GPL-2-CP. See the
011: * License for the specific language governing permissions and limitations under the
012: * License. When distributing the software, include this License Header Notice in
013: * each file and include the License file at nbbuild/licenses/CDDL-GPL-2-CP. Sun
014: * designates this particular file as subject to the "Classpath" exception as
015: * provided by Sun in the GPL Version 2 section of the License file that
016: * accompanied this code. If applicable, add the following below the License Header,
017: * with the fields enclosed by brackets [] replaced by your own identifying
018: * information: "Portions Copyrighted [year] [name of copyright owner]"
019: *
020: * Contributor(s):
021: *
022: * The Original Software is NetBeans. The Initial Developer of the Original Software
023: * is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun Microsystems, Inc. All
024: * Rights Reserved.
025: *
026: * If you wish your version of this file to be governed by only the CDDL or only the
027: * GPL Version 2, indicate your decision by adding "[Contributor] elects to include
028: * this software in this distribution under the [CDDL or GPL Version 2] license." If
029: * you do not indicate a single choice of license, a recipient has the option to
030: * distribute your version of this file under either the CDDL, the GPL Version 2 or
031: * to extend the choice of license to its licensees as provided above. However, if
032: * you add GPL Version 2 code and therefore, elected the GPL Version 2 license, then
033: * the option applies only if the new code is made subject to such option by the
034: * copyright holder.
035: */
036:
037: package org.netbeans.installer.utils.system;
038:
039: import java.io.File;
040: import java.io.IOException;
041: import java.io.InputStream;
042: import java.util.ArrayList;
043: import java.util.HashSet;
044: import java.util.List;
045: import org.netbeans.installer.Installer;
046: import org.netbeans.installer.utils.helper.EnvironmentScope;
047: import org.netbeans.installer.utils.ErrorManager;
048: import org.netbeans.installer.utils.FileUtils;
049: import org.netbeans.installer.utils.LogManager;
050: import org.netbeans.installer.utils.system.shortcut.Shortcut;
051: import org.netbeans.installer.utils.SystemUtils;
052: import org.netbeans.installer.utils.exceptions.NativeException;
053: import org.netbeans.installer.utils.helper.ApplicationDescriptor;
054: import org.netbeans.installer.utils.helper.FilesList;
055: import org.netbeans.installer.utils.helper.Platform;
056: import org.netbeans.installer.utils.system.launchers.Launcher;
057: import org.netbeans.installer.utils.system.launchers.LauncherResource;
058: import org.netbeans.installer.utils.progress.Progress;
059: import org.netbeans.installer.utils.system.cleaner.OnExitCleanerHandler;
060: import org.netbeans.installer.utils.system.cleaner.JavaOnExitCleanerHandler;
061: import org.netbeans.installer.utils.system.launchers.LauncherProperties;
062: import org.netbeans.installer.utils.system.shortcut.LocationType;
063:
064: /**
065: *
066: * @author Kirill Sorokin
067: */
068: public abstract class NativeUtils {
069: /////////////////////////////////////////////////////////////////////////////////
070: // Static
071: private static NativeUtils instance;
072: private static HashSet<File> forbiddenDeletingFiles = new HashSet<File>();
073: private static List<LauncherResource> uninstallerJVMs = new ArrayList<LauncherResource>();
074: private static List<File> deleteOnExitFiles = new ArrayList<File>();
075: public final static String NATIVE_RESOURCE_SUFFIX = "native/"; // NOI18N
076: public final static String NATIVE_JNILIB_RESOURCE_SUFFIX = NATIVE_RESOURCE_SUFFIX
077: + "jnilib/"; // NOI18N
078: public final static String NATIVE_LAUNCHER_RESOURCE_SUFFIX = NATIVE_RESOURCE_SUFFIX
079: + "launcher/"; // NOI18N
080: public final static String NATIVE_CLEANER_RESOURCE_SUFFIX = NATIVE_RESOURCE_SUFFIX
081: + "cleaner/"; // NOI18N
082: private static OnExitCleanerHandler cleanerHandler;
083:
084: public static synchronized NativeUtils getInstance() {
085: final Platform platform = SystemUtils.getCurrentPlatform();
086:
087: if (platform.isCompatibleWith(Platform.WINDOWS)) {
088: instance = new WindowsNativeUtils();
089: } else if (platform.isCompatibleWith(Platform.LINUX)) {
090: instance = new LinuxNativeUtils();
091: } else if (platform.isCompatibleWith(Platform.SOLARIS)) {
092: instance = new SolarisNativeUtils();
093: } else if (platform.isCompatibleWith(Platform.MACOSX)) {
094: instance = new MacOsNativeUtils();
095: }
096:
097: return instance;
098: }
099:
100: /////////////////////////////////////////////////////////////////////////////////
101: // Instance
102:
103: // constructor //////////////////////////////////////////////////////////////////
104: protected NativeUtils() {
105: // does nothing
106: }
107:
108: // abstract /////////////////////////////////////////////////////////////////////
109: public abstract boolean isCurrentUserAdmin() throws NativeException;
110:
111: public abstract File getDefaultApplicationsLocation()
112: throws NativeException;
113:
114: public abstract long getFreeSpace(File file) throws NativeException;
115:
116: public abstract boolean isPathValid(String path);
117:
118: public abstract boolean isUNCPath(String path);
119:
120: public File getRoot(final File file) {
121: File parent = file;
122: while (parent.getParentFile() != null) {
123: parent = parent.getParentFile();
124: }
125:
126: return parent;
127: }
128:
129: public abstract File getShortcutLocation(Shortcut shortcut,
130: LocationType locationType) throws NativeException;
131:
132: public abstract File createShortcut(Shortcut shortcut,
133: LocationType locationType) throws NativeException;
134:
135: public abstract void removeShortcut(Shortcut shortcut,
136: LocationType locationType, boolean deleteEmptyParents)
137: throws NativeException;
138:
139: public void addUninstallerJVM(LauncherResource jvm) {
140: if (jvm != null && !uninstallerJVMs.contains(jvm)) {
141: uninstallerJVMs.add(jvm);
142: }
143: }
144:
145: protected Launcher createUninstaller(
146: ApplicationDescriptor descriptor, boolean uninstall,
147: Progress progress) throws IOException {
148: LogManager.log("creating uninstaller...");
149:
150: final File engine = new File(descriptor.getInstallPath(),
151: "uninstall.jar");
152: try {
153: Installer.cacheInstallerEngine(engine, new Progress());
154:
155: final LauncherProperties props = new LauncherProperties();
156:
157: props.addJVM(new LauncherResource(false, SystemUtils
158: .getCurrentJavaHome()));
159: for (LauncherResource jvm : uninstallerJVMs) {
160: props.addJVM(jvm);
161: }
162: props.addJar(new LauncherResource(true, engine));
163: props
164: .setJvmArguments(new String[] {
165: "-Xmx256m",
166: "-Xms64m",
167: "-D"
168: + Installer.LOCAL_DIRECTORY_PATH_PROPERTY
169: + "="
170: + new File(
171: System
172: .getProperty(Installer.LOCAL_DIRECTORY_PATH_PROPERTY))
173: .getAbsolutePath() });
174: props.setMainClass(Installer.class.getName());
175:
176: if (uninstall) {
177: props.setAppArguments(descriptor.getUninstallCommand());
178: props.setOutput(new File(descriptor.getInstallPath(),
179: "uninstall"), true);
180: } else {
181: props.setAppArguments(descriptor.getModifyCommand());
182: props.setOutput(new File(descriptor.getInstallPath(),
183: "modify-install"), true);
184: }
185: return SystemUtils.createLauncher(props, progress);
186: } finally {
187: FileUtils.deleteFile(engine);
188: }
189: }
190:
191: public abstract FilesList addComponentToSystemInstallManager(
192: ApplicationDescriptor descriptor) throws NativeException;
193:
194: public abstract void removeComponentFromSystemInstallManager(
195: ApplicationDescriptor descriptor) throws NativeException;
196:
197: public abstract String getEnvironmentVariable(String name,
198: EnvironmentScope scope, boolean expand)
199: throws NativeException;
200:
201: public abstract void setEnvironmentVariable(String name,
202: String value, EnvironmentScope scope, boolean expand)
203: throws NativeException;
204:
205: public abstract List<File> findIrrelevantFiles(File parent)
206: throws IOException;
207:
208: public abstract List<File> findExecutableFiles(File parent)
209: throws IOException;
210:
211: public abstract void correctFilesPermissions(File parent)
212: throws IOException;
213:
214: public abstract void setPermissions(final File file,
215: final int mode, final int change) throws IOException;
216:
217: public abstract int getPermissions(final File file)
218: throws IOException;
219:
220: public boolean checkFileAccess(File file, boolean isReadNotModify)
221: throws NativeException {
222: return true;
223: }
224:
225: private final void initializeDeteleOnExit() {
226:
227: }
228:
229: public final void addDeleteOnExitFile(File file) {
230: getDeleteOnExitHandler().addDeleteOnExitFile(file);
231: }
232:
233: public final void removeDeleteOnExitFile(File file) {
234: getDeleteOnExitHandler().removeDeleteOnExitFile(file);
235: }
236:
237: protected OnExitCleanerHandler newDeleteOnExitCleanerHandler() {
238: return new JavaOnExitCleanerHandler();
239: }
240:
241: protected OnExitCleanerHandler getDeleteOnExitHandler() {
242: if (cleanerHandler == null) {
243: cleanerHandler = newDeleteOnExitCleanerHandler();
244: Runtime.getRuntime().addShutdownHook(cleanerHandler);
245: }
246: return cleanerHandler;
247: }
248:
249: public abstract List<File> getFileSystemRoots() throws IOException;
250:
251: // protected ////////////////////////////////////////////////////////////////////
252: protected void loadNativeLibrary(String path) {
253: LogManager.logIndent("loading jni library");
254: LogManager.log("library resource path: " + path);
255:
256: if (path != null) {
257: InputStream input = null;
258:
259: try {
260: final File file = FileUtils.createTempFile();
261:
262: LogManager.log("library file path: "
263: + file.getAbsolutePath());
264:
265: input = getClass().getClassLoader()
266: .getResourceAsStream(path);
267: FileUtils.writeFile(file, input);
268:
269: System.load(file.getAbsolutePath());
270:
271: addDeleteOnExitFile(file);
272: } catch (IOException e) {
273: ErrorManager
274: .notifyCritical(
275: "Cannot load native library from path: "
276: + path, e);
277: } catch (UnsatisfiedLinkError e) {
278: ErrorManager
279: .notifyCritical(
280: "Cannot load native library from path: "
281: + path, e);
282: } finally {
283: if (input != null) {
284: try {
285: input.close();
286: } catch (IOException e) {
287: ErrorManager
288: .notifyDebug(
289: "Failed to close the input "
290: + "stream to the cached jni library",
291: e);
292: }
293: }
294: }
295: }
296:
297: LogManager.logUnindent("... successfully loaded the library");
298: }
299:
300: protected void initializeForbiddenFiles(String... filepaths) {
301: for (String path : filepaths) {
302: if (path != null) {
303: File file = new File(path);
304: if (file.exists()) {
305: forbiddenDeletingFiles.add(file);
306: }
307: }
308: }
309: }
310:
311: public boolean isDeletingAllowed(File file) {
312: return !(forbiddenDeletingFiles.contains(file));
313: }
314:
315: public final static int FA_MODE_SET = 1;
316: public final static int FA_MODE_ADD = 2;
317: public final static int FA_MODE_REMOVE = 4;
318: }
|