/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common
* Development and Distribution License("CDDL") (collectively, the
* "License"). You may not use this file except in compliance with the
* License. You can obtain a copy of the License at
* http://www.netbeans.org/cddl-gplv2.html
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
* specific language governing permissions and limitations under the
* License. When distributing the software, include this License Header
* Notice in each file and include the License file at
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the
* License Header, with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* Contributor(s):
*
* The Original Software is NetBeans. The Initial Developer of the Original
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
* Microsystems, Inc. All Rights Reserved.
*
* If you wish your version of this file to be governed by only the CDDL
* or only the GPL Version 2, indicate your decision by adding
* "[Contributor] elects to include this software in this distribution
* under the [CDDL or GPL Version 2] license." If you do not indicate a
* single choice of license, a recipient has the option to distribute
* your version of this file under either the CDDL, the GPL Version 2 or
* to extend the choice of license to its licensees as provided above.
* However, if you add GPL Version 2 code and therefore, elected the GPL
* Version 2 license, then the option applies only if the new code is
* made subject to such option by the copyright holder.
*/
package org.netbeans.modules.scala.project.applet;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.Tree;
import com.sun.source.util.TreePath;
import com.sun.source.util.Trees;
import java.io.*;
import java.net.*;
import java.util.*;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import org.netbeans.api.java.source.CancellableTask;
import org.netbeans.api.java.source.CompilationController;
import org.netbeans.api.java.source.JavaSource;
import org.openide.*;
import org.openide.modules.SpecificationVersion;
import org.openide.filesystems.*;
import org.openide.util.*;
import org.netbeans.api.java.classpath.*;
import org.netbeans.api.java.platform.*;
import org.netbeans.modules.scala.project.J2SEProjectUtil;
/** Support for execution of applets.
*
* @author Ales Novak, Martin Grebac
*/
public class AppletSupport {
// JDK issue #6193279: Appletviewer does not accept encoded URLs
private static final SpecificationVersion JDK_15 = new SpecificationVersion("1.5"); // NOI18N
/** constant for html extension */
private static final String HTML_EXT = "html"; // NOI18N
/** constant for class extension */
private static final String CLASS_EXT = "class"; // NOI18N
private final static String POLICY_FILE_NAME = "applet";
private final static String POLICY_FILE_EXT = "policy";
private AppletSupport() {}
// Used only from unit tests to suppress detection of applet. If value
// is different from null it will be returned instead.
public static Boolean unitTestingSupport_isApplet = null;
public static boolean isApplet(final FileObject file) {
if (file == null) {
return false;
}
// support for unit testing
if (unitTestingSupport_isApplet != null) {
return unitTestingSupport_isApplet.booleanValue();
}
JavaSource js = JavaSource.forFileObject(file);
if (js == null) {
return false;
}
final boolean[] result = new boolean[] {false};
try {
js.runUserActionTask(new CancellableTask<CompilationController>() {
public void run(CompilationController control) throws Exception {
if (JavaSource.Phase.ELEMENTS_RESOLVED.compareTo(control.toPhase(JavaSource.Phase.ELEMENTS_RESOLVED))<=0) {
Elements elements = control.getElements();
Trees trees = control.getTrees();
Types types = control.getTypes();
TypeElement applet = elements.getTypeElement("java.applet.Applet"); //NOI18N
TypeElement japplet = elements.getTypeElement("javax.swing.JApplet"); //NOI18N
CompilationUnitTree cu = control.getCompilationUnit();
List<? extends Tree> topLevels = cu.getTypeDecls();
for (Tree topLevel : topLevels) {
if (topLevel.getKind() == Tree.Kind.CLASS) {
TypeElement type = (TypeElement) trees.getElement(TreePath.getPath(cu, topLevel));
if (type != null) {
Set<Modifier> modifiers = type.getModifiers();
if (modifiers.contains(Modifier.PUBLIC) &&
((applet != null && types.isSubtype(type.asType(), applet.asType()))
|| (japplet != null && types.isSubtype(type.asType(), japplet.asType())))) {
result[0] = true;
break;
}
}
}
}
}
}
public void cancel() {}
}, true);
} catch (IOException ioe) {
Exceptions.printStackTrace(ioe);
}
return result[0];
}
/**
* @return html file with the same name as applet
*/
private static FileObject generateHtml(FileObject appletFile, FileObject buildDir, FileObject classesDir) throws IOException {
FileObject htmlFile = buildDir.getFileObject(appletFile.getName(), HTML_EXT);
if (htmlFile == null) {
htmlFile = buildDir.createData(appletFile.getName(), HTML_EXT);
}
FileLock lock = htmlFile.lock();
PrintWriter writer = null;
try {
writer = new PrintWriter(htmlFile.getOutputStream(lock));
ClassPath cp = ClassPath.getClassPath(appletFile, ClassPath.EXECUTE);
ClassPath sp = ClassPath.getClassPath(appletFile, ClassPath.SOURCE);
String path = FileUtil.getRelativePath(sp.findOwnerRoot(appletFile), appletFile);
path = path.substring(0, path.length()-5);
String codebase = FileUtil.getRelativePath(buildDir, classesDir);
if (codebase == null) {
codebase = classesDir.getURL().toString();
}
fillInFile(writer, path + "." + CLASS_EXT, "codebase=\"" + codebase + "\""); // NOI18N
} finally {
lock.releaseLock();
if (writer != null)
writer.close();
}
return htmlFile;
}
/**
* @return html file with the same name as applet
*/
public static FileObject generateSecurityPolicy(FileObject projectDir) {
FileObject policyFile = projectDir.getFileObject(POLICY_FILE_NAME, POLICY_FILE_EXT);
try {
if (policyFile == null) {
policyFile = projectDir.createData(POLICY_FILE_NAME, POLICY_FILE_EXT);
}
FileLock lock = policyFile.lock();
PrintWriter writer = null;
try {
writer = new PrintWriter(policyFile.getOutputStream(lock));
fillInPolicyFile(writer);
} finally {
lock.releaseLock();
if (writer != null)
writer.close();
}
} catch (IOException ioe) {
ErrorManager.getDefault().log(ErrorManager.INFORMATIONAL, "Problem when generating applet policy file: " + ioe); //NOI18N
}
return policyFile;
}
/**
* @return URL of the html file with the same name as sibling
*/
// public static URL generateHtmlFileURL(FileObject appletFile, FileObject buildDir, FileObject classesDir, String activePlatform) throws FileStateInvalidException {
// FileObject html = null;
// IOException ex = null;
// if ((appletFile == null) || (buildDir == null) || (classesDir == null)) {
// return null;
// }
// try {
// html = generateHtml(appletFile, buildDir, classesDir);
// if (html!=null) {
// return getHTMLPageURL(html, activePlatform);
// }
// else {
// return null;
// }
// } catch (IOException iex) {
// return null;
// }
// }
/**
* Creates an URL of html page passed to the appletviewer. It workarounds a JDK 1.5 appletviewer
* bug. The appletviewer is not able to handle escaped URLs.
* @param htmlFile html page
* @param activePlatform identifier of the platform used in the project
* @return URL of the html page or null
*/
// public static URL getHTMLPageURL (FileObject htmlFile, String activePlatform) {
// assert htmlFile != null : "htmlFile cannot be null"; //NOI18N
// // JDK issue #6193279: Appletviewer does not accept encoded URLs
// JavaPlatform platform = J2SEProjectUtil.getActivePlatform(activePlatform);
// boolean workAround6193279 = platform != null //In case of nonexisting platform don't use the workaround
// && platform.getSpecification().getVersion().compareTo(JDK_15)>=0; //JDK1.5 and higher
// URL url = null;
// if (workAround6193279) {
// File f = FileUtil.toFile(htmlFile);
// try {
// String path = f.getAbsolutePath();
// if (File.separatorChar != '/') { //NOI18N
// path = path.replace(File.separatorChar,'/'); //NOI18N
// }
// url = new URL ("file",null,path);
// } catch (MalformedURLException e) {
// ErrorManager.getDefault().notify(e);
// }
// }
// else {
// try {
// url = htmlFile.getURL();
// } catch (FileStateInvalidException f) {
// ErrorManager.getDefault().notify(f);
// }
// }
// return url;
// }
/** fills in file with html source so it is html file with applet
* @param file is a file to be filled
* @param name is name of the applet
*/
private static void fillInFile(PrintWriter writer, String name, String codebase) {
ResourceBundle bundle = NbBundle.getBundle(AppletSupport.class);
writer.println("<HTML>"); // NOI18N
writer.println("<HEAD>"); // NOI18N
writer.print(" <TITLE>"); // NOI18N
writer.print(bundle.getString("GEN_title"));
writer.println("</TITLE>"); // NOI18N
writer.println("</HEAD>"); // NOI18N
writer.println("<BODY>\n"); // NOI18N
writer.print(bundle.getString("GEN_warning"));
writer.print("<H3><HR WIDTH=\"100%\">"); // NOI18N
writer.print(bundle.getString("GEN_header"));
writer.println("<HR WIDTH=\"100%\"></H3>\n"); // NOI18N
writer.println("<P>"); // NOI18N
// String codebase = getCodebase (name);
if (codebase == null)
writer.print("<APPLET code="); // NOI18N
else
writer.print("<APPLET " + codebase + " code="); // NOI18N
writer.print ("\""); // NOI18N
writer.print(name);
writer.print ("\""); // NOI18N
writer.println(" width=350 height=200></APPLET>"); // NOI18N
writer.println("</P>\n"); // NOI18N
writer.print("<HR WIDTH=\"100%\"><FONT SIZE=-1><I>"); // NOI18N
writer.print(bundle.getString("GEN_copy"));
writer.println("</I></FONT>"); // NOI18N
writer.println("</BODY>"); // NOI18N
writer.println("</HTML>"); // NOI18N
writer.flush();
}
/** fills in policy file with all permissions granted
* @param writer is a file to be filled
*/
private static void fillInPolicyFile(PrintWriter writer) {
writer.println("grant {"); // NOI18N
writer.println("permission java.security.AllPermission;"); // NOI18N
writer.println("};"); // NOI18N
writer.flush();
}
}