import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.Set;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.NestingKind;
import javax.tools.FileObject;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.JavaFileObject.Kind;
import javax.tools.ToolProvider;
class Ideone {
String src
="public class Test {\r\n" + " public static void main(String[] args) {\r\n" +
" System.out.println(\"Hello \"+args[0]+\"!\");\r\n" +
" }\r\n" +
"}";
List
<JFO
> sources
=Arrays.
asList(new JFO
(name,src
)); Map
<String,JFO
> files
=new HashMap
<>(); JavaCompiler jc=ToolProvider.getSystemJavaCompiler();
JavaCompiler.CompilationTask ct=jc.getTask(null, new JFM(jc.getStandardFileManager(null, null, null),files), null, null, null, sources);
System.
out.
println(ct.
call()); Class<?> clazz=new CL().defineClass(name, files.get(name).baos.toByteArray());
clazz.
getDeclaredMethod("main",
String[].
class).
invoke(null,
(Object)new String[] {"StackOverflow"}); }
static class JFO implements JavaFileObject {
this.name=name;
this.src=src;
}
@Override
public URI toUri() {
URI uri=null;
try {
uri=new URI(name);
}catch(URISyntaxException use) {use.printStackTrace();};
System.
out.
println("toUri "+uri
); return uri;
}
@Override
System.
out.
println("getName "+name
); return name;
}
@Override
}
@Override
System.
out.
println("openOutputStream"); if(baos
!=null)throw new Error(); return baos;
}
@Override
}
@Override
public CharSequence getCharContent
(boolean ignoreEncodingErrors
) throws IOException { System.
out.
println("getCharContent"); return src;
}
@Override
}
@Override
public long getLastModified() {
}
@Override
public boolean delete() {
}
@Override
public Kind getKind() {
System.
out.
println("getKind"); return Kind.SOURCE;
}
@Override
public boolean isNameCompatible
(String simpleName, Kind kind
) { System.
out.
println("isNameCompatible "+name
+" ? "+simpleName
); return name.equals(simpleName);
}
@Override
public NestingKind getNestingKind() {
}
@Override
}
}
static class JFM implements JavaFileManager {
final JavaFileManager jfm;
JFM
(JavaFileManager jfm, Map
<String, JFO
> files
){ this.jfm=jfm;
this.files=files;
}
@Override
public int isSupportedOption
(String option
) { int iso=jfm.isSupportedOption(option);
System.
out.
println("isSupportedOption "+option
+" "+iso
); return iso;
}
@Override
System.
out.
println("getClassLoader "+location
+" "+cl
); return cl;
}
@Override
public Iterable
<JavaFileObject
> list
(Location location,
String packageName, Set
<Kind
> kinds,
boolean recurse
) System.
out.
println("list "+location
+" "+packageName
+" ... "+recurse
); return jfm.list(location, packageName, kinds, recurse);
}
@Override
public String inferBinaryName
(Location location, JavaFileObject file
) { String ibm
=jfm.
inferBinaryName(location, file
); // System.out.println("inferBinaryName "+location+" "+file+" "+ibm);
return ibm;
}
@Override
public boolean isSameFile(FileObject a, FileObject b) {
}
@Override
public boolean handleOption
(String current, Iterator
<String
> remaining
) { boolean ho=jfm.handleOption(current, remaining);
System.
out.
println("handleOption "+current
+" ..."); return ho;
}
@Override
public boolean hasLocation(Location location) {
boolean hl=jfm.hasLocation(location);
// System.out.println("hasLocation "+location+" "+hl);
return hl;
}
@Override
public JavaFileObject getJavaFileForInput
(Location location,
String className, Kind kind
) throws IOException { // System.out.println("getJavaFileForInput "+location+" "+className+" "+kind.name());
return jfm.getJavaFileForInput(location, className, kind);
}
@Override
public JavaFileObject getJavaFileForOutput
(Location location,
String className, Kind kind, FileObject sibling
) System.
out.
println("getJavaFileForOutput "+location
+" "+className
+" "+kind.
name()+" "+sibling
); if(files.containsKey(className))
JFO jfo=new JFO(className,null);
files.put(className, jfo);
return jfo;
}
@Override
public FileObject getFileForInput
(Location location,
String packageName,
String relativeName
) }
@Override
public FileObject getFileForOutput
(Location location,
String packageName,
String relativeName,
}
@Override
}
@Override
}
public Location getLocationForModule
(Location location,
String moduleName
) throws IOException { }
public Location getLocationForModule
(Location location, JavaFileObject fo
) throws IOException { }
public <S
> ServiceLoader
<S
> getServiceLoader
(Location location, Class
<S
> service
) throws IOException { }
String imm
=jfm.
inferModuleName(location
); // System.out.println("inferModuleName "+location+" "+imm);
return imm;
}
public Iterable
<Set
<Location
>> listLocationsForModules
(Location location
) throws IOException { Iterable<Set<Location>> llfm=jfm.listLocationsForModules(location);
System.
out.
println("listLocationsForModules "+location
+" ..."); return llfm;
}
public boolean contains
(Location location, FileObject fo
) throws IOException { }
}
public Class
<?> defineClass
(String name,
byte array
[]) { return defineClass(name, array, 0, array.length);
}
}
}
aW1wb3J0IGphdmEuaW8uQnl0ZUFycmF5T3V0cHV0U3RyZWFtOwppbXBvcnQgamF2YS5pby5JT0V4Y2VwdGlvbjsKaW1wb3J0IGphdmEuaW8uSW5wdXRTdHJlYW07CmltcG9ydCBqYXZhLmlvLk91dHB1dFN0cmVhbTsKaW1wb3J0IGphdmEuaW8uUmVhZGVyOwppbXBvcnQgamF2YS5pby5Xcml0ZXI7CmltcG9ydCBqYXZhLm5ldC5VUkk7CmltcG9ydCBqYXZhLm5ldC5VUklTeW50YXhFeGNlcHRpb247CmltcG9ydCBqYXZhLnV0aWwuQXJyYXlzOwppbXBvcnQgamF2YS51dGlsLkhhc2hNYXA7CmltcG9ydCBqYXZhLnV0aWwuSXRlcmF0b3I7CmltcG9ydCBqYXZhLnV0aWwuTGlzdDsKaW1wb3J0IGphdmEudXRpbC5NYXA7CmltcG9ydCBqYXZhLnV0aWwuU2VydmljZUxvYWRlcjsKaW1wb3J0IGphdmEudXRpbC5TZXQ7CgppbXBvcnQgamF2YXgubGFuZy5tb2RlbC5lbGVtZW50Lk1vZGlmaWVyOwppbXBvcnQgamF2YXgubGFuZy5tb2RlbC5lbGVtZW50Lk5lc3RpbmdLaW5kOwppbXBvcnQgamF2YXgudG9vbHMuRmlsZU9iamVjdDsKaW1wb3J0IGphdmF4LnRvb2xzLkphdmFDb21waWxlcjsKaW1wb3J0IGphdmF4LnRvb2xzLkphdmFGaWxlTWFuYWdlcjsKaW1wb3J0IGphdmF4LnRvb2xzLkphdmFGaWxlT2JqZWN0OwppbXBvcnQgamF2YXgudG9vbHMuSmF2YUZpbGVPYmplY3QuS2luZDsKaW1wb3J0IGphdmF4LnRvb2xzLlRvb2xQcm92aWRlcjsKCmNsYXNzIElkZW9uZSB7CglwdWJsaWMgc3RhdGljIHZvaWQgbWFpbihTdHJpbmdbXSBhcmdzKSB0aHJvd3MgRXhjZXB0aW9uIHsKCQlTdHJpbmcgbmFtZT0iVGVzdCI7CgkJU3RyaW5nIHNyYz0icHVibGljIGNsYXNzIFRlc3Qge1xyXG4iICsgCgkJCQkiICBwdWJsaWMgc3RhdGljIHZvaWQgbWFpbihTdHJpbmdbXSBhcmdzKSB7XHJcbiIgKyAKCQkJCSIgICAgU3lzdGVtLm91dC5wcmludGxuKFwiSGVsbG8gXCIrYXJnc1swXStcIiFcIik7XHJcbiIgKyAKCQkJCSIgIH1cclxuIiArIAoJCQkJIn0iOwoJCVN5c3RlbS5vdXQucHJpbnRsbihzcmMpOwoJCUxpc3Q8SkZPPiBzb3VyY2VzPUFycmF5cy5hc0xpc3QobmV3IEpGTyhuYW1lLHNyYykpOwoJCU1hcDxTdHJpbmcsSkZPPiBmaWxlcz1uZXcgSGFzaE1hcDw+KCk7CgkJSmF2YUNvbXBpbGVyIGpjPVRvb2xQcm92aWRlci5nZXRTeXN0ZW1KYXZhQ29tcGlsZXIoKTsKCQlKYXZhQ29tcGlsZXIuQ29tcGlsYXRpb25UYXNrIGN0PWpjLmdldFRhc2sobnVsbCwgbmV3IEpGTShqYy5nZXRTdGFuZGFyZEZpbGVNYW5hZ2VyKG51bGwsIG51bGwsIG51bGwpLGZpbGVzKSwgbnVsbCwgbnVsbCwgbnVsbCwgc291cmNlcyk7CgkJU3lzdGVtLm91dC5wcmludGxuKGN0LmNhbGwoKSk7CgkJQ2xhc3M8Pz4gY2xheno9bmV3IENMKCkuZGVmaW5lQ2xhc3MobmFtZSwgZmlsZXMuZ2V0KG5hbWUpLmJhb3MudG9CeXRlQXJyYXkoKSk7CgkJY2xhenouZ2V0RGVjbGFyZWRNZXRob2QoIm1haW4iLCBTdHJpbmdbXS5jbGFzcykuaW52b2tlKG51bGwsIChPYmplY3QpbmV3IFN0cmluZ1tdIHsiU3RhY2tPdmVyZmxvdyJ9KTsKCX0KCQoJc3RhdGljIGNsYXNzIEpGTyBpbXBsZW1lbnRzIEphdmFGaWxlT2JqZWN0IHsKCQlmaW5hbCBTdHJpbmcgbmFtZTsKCQlmaW5hbCBTdHJpbmcgc3JjOwoJCUpGTyhTdHJpbmcgbmFtZSxTdHJpbmcgc3JjKXsKCQkJdGhpcy5uYW1lPW5hbWU7CgkJCXRoaXMuc3JjPXNyYzsKCQl9CgkJQE92ZXJyaWRlCgkJcHVibGljIFVSSSB0b1VyaSgpIHsKCQkJVVJJIHVyaT1udWxsOwoJCQl0cnkgewoJCQkJdXJpPW5ldyBVUkkobmFtZSk7CgkJCX1jYXRjaChVUklTeW50YXhFeGNlcHRpb24gdXNlKSB7dXNlLnByaW50U3RhY2tUcmFjZSgpO307CgkJCVN5c3RlbS5vdXQucHJpbnRsbigidG9VcmkgIit1cmkpOwoJCQlyZXR1cm4gdXJpOwoJCX0KCgkJQE92ZXJyaWRlCgkJcHVibGljIFN0cmluZyBnZXROYW1lKCkgewoJCQlTeXN0ZW0ub3V0LnByaW50bG4oImdldE5hbWUgIituYW1lKTsKCQkJcmV0dXJuIG5hbWU7CgkJfQoKCQlAT3ZlcnJpZGUKCQlwdWJsaWMgSW5wdXRTdHJlYW0gb3BlbklucHV0U3RyZWFtKCkgdGhyb3dzIElPRXhjZXB0aW9uIHsKCQkJdGhyb3cgbmV3IEVycm9yKCk7CgkJfQoKCQlCeXRlQXJyYXlPdXRwdXRTdHJlYW0gYmFvczsKCQlAT3ZlcnJpZGUKCQlwdWJsaWMgT3V0cHV0U3RyZWFtIG9wZW5PdXRwdXRTdHJlYW0oKSB0aHJvd3MgSU9FeGNlcHRpb24gewoJCQlTeXN0ZW0ub3V0LnByaW50bG4oIm9wZW5PdXRwdXRTdHJlYW0iKTsKCQkJaWYoYmFvcyE9bnVsbCl0aHJvdyBuZXcgRXJyb3IoKTsKCQkJYmFvcz1uZXcgQnl0ZUFycmF5T3V0cHV0U3RyZWFtKCk7CgkJCXJldHVybiBiYW9zOwoJCX0KCgkJQE92ZXJyaWRlCgkJcHVibGljIFJlYWRlciBvcGVuUmVhZGVyKGJvb2xlYW4gaWdub3JlRW5jb2RpbmdFcnJvcnMpIHRocm93cyBJT0V4Y2VwdGlvbiB7CgkJCXRocm93IG5ldyBFcnJvcigpOwoJCX0KCgkJQE92ZXJyaWRlCgkJcHVibGljIENoYXJTZXF1ZW5jZSBnZXRDaGFyQ29udGVudChib29sZWFuIGlnbm9yZUVuY29kaW5nRXJyb3JzKSB0aHJvd3MgSU9FeGNlcHRpb24gewoJCQlTeXN0ZW0ub3V0LnByaW50bG4oImdldENoYXJDb250ZW50Iik7CgkJCXJldHVybiBzcmM7CgkJfQoKCQlAT3ZlcnJpZGUKCQlwdWJsaWMgV3JpdGVyIG9wZW5Xcml0ZXIoKSB0aHJvd3MgSU9FeGNlcHRpb24gewoJCQl0aHJvdyBuZXcgRXJyb3IoKTsKCQl9CgoJCUBPdmVycmlkZQoJCXB1YmxpYyBsb25nIGdldExhc3RNb2RpZmllZCgpIHsKCQkJdGhyb3cgbmV3IEVycm9yKCk7CgkJfQoKCQlAT3ZlcnJpZGUKCQlwdWJsaWMgYm9vbGVhbiBkZWxldGUoKSB7CgkJCXRocm93IG5ldyBFcnJvcigpOwoJCX0KCgkJQE92ZXJyaWRlCgkJcHVibGljIEtpbmQgZ2V0S2luZCgpIHsKCQkJU3lzdGVtLm91dC5wcmludGxuKCJnZXRLaW5kIik7CgkJCXJldHVybiBLaW5kLlNPVVJDRTsKCQl9CgoJCUBPdmVycmlkZQoJCXB1YmxpYyBib29sZWFuIGlzTmFtZUNvbXBhdGlibGUoU3RyaW5nIHNpbXBsZU5hbWUsIEtpbmQga2luZCkgewoJCQlTeXN0ZW0ub3V0LnByaW50bG4oImlzTmFtZUNvbXBhdGlibGUgIituYW1lKyIgPyAiK3NpbXBsZU5hbWUpOwoJCQlyZXR1cm4gbmFtZS5lcXVhbHMoc2ltcGxlTmFtZSk7CgkJfQoKCQlAT3ZlcnJpZGUKCQlwdWJsaWMgTmVzdGluZ0tpbmQgZ2V0TmVzdGluZ0tpbmQoKSB7CgkJCXRocm93IG5ldyBFcnJvcigpOwoJCX0KCgkJQE92ZXJyaWRlCgkJcHVibGljIE1vZGlmaWVyIGdldEFjY2Vzc0xldmVsKCkgewoJCQl0aHJvdyBuZXcgRXJyb3IoKTsKCQl9CgkJCgl9CgkKCXN0YXRpYyBjbGFzcyBKRk0gaW1wbGVtZW50cyBKYXZhRmlsZU1hbmFnZXIgewoJCWZpbmFsIEphdmFGaWxlTWFuYWdlciBqZm07CgkJZmluYWwgTWFwPFN0cmluZywgSkZPPiBmaWxlczsKCQlKRk0oSmF2YUZpbGVNYW5hZ2VyIGpmbSwgTWFwPFN0cmluZywgSkZPPiBmaWxlcyl7CgkJCXRoaXMuamZtPWpmbTsKCQkJdGhpcy5maWxlcz1maWxlczsKCQl9CgoJCUBPdmVycmlkZQoJCXB1YmxpYyBpbnQgaXNTdXBwb3J0ZWRPcHRpb24oU3RyaW5nIG9wdGlvbikgewoJCQlpbnQgaXNvPWpmbS5pc1N1cHBvcnRlZE9wdGlvbihvcHRpb24pOwoJCQlTeXN0ZW0ub3V0LnByaW50bG4oImlzU3VwcG9ydGVkT3B0aW9uICIrb3B0aW9uKyIgIitpc28pOwoJCQlyZXR1cm4gaXNvOwoJCX0KCgkJQE92ZXJyaWRlCgkJcHVibGljIENsYXNzTG9hZGVyIGdldENsYXNzTG9hZGVyKExvY2F0aW9uIGxvY2F0aW9uKSB7CgkJCUNsYXNzTG9hZGVyIGNsPWpmbS5nZXRDbGFzc0xvYWRlcihsb2NhdGlvbik7CgkJCVN5c3RlbS5vdXQucHJpbnRsbigiZ2V0Q2xhc3NMb2FkZXIgIitsb2NhdGlvbisiICIrY2wpOwoJCQlyZXR1cm4gY2w7CgkJfQoKCQlAT3ZlcnJpZGUKCQlwdWJsaWMgSXRlcmFibGU8SmF2YUZpbGVPYmplY3Q+IGxpc3QoTG9jYXRpb24gbG9jYXRpb24sIFN0cmluZyBwYWNrYWdlTmFtZSwgU2V0PEtpbmQ+IGtpbmRzLCBib29sZWFuIHJlY3Vyc2UpCgkJCQl0aHJvd3MgSU9FeGNlcHRpb24gewoJCQlTeXN0ZW0ub3V0LnByaW50bG4oImxpc3QgIitsb2NhdGlvbisiICIrcGFja2FnZU5hbWUrIiAuLi4gIityZWN1cnNlKTsKCQkJcmV0dXJuIGpmbS5saXN0KGxvY2F0aW9uLCBwYWNrYWdlTmFtZSwga2luZHMsIHJlY3Vyc2UpOwoJCX0KCgkJQE92ZXJyaWRlCgkJcHVibGljIFN0cmluZyBpbmZlckJpbmFyeU5hbWUoTG9jYXRpb24gbG9jYXRpb24sIEphdmFGaWxlT2JqZWN0IGZpbGUpIHsKCQkJU3RyaW5nIGlibT1qZm0uaW5mZXJCaW5hcnlOYW1lKGxvY2F0aW9uLCBmaWxlKTsKLy8JCQlTeXN0ZW0ub3V0LnByaW50bG4oImluZmVyQmluYXJ5TmFtZSAiK2xvY2F0aW9uKyIgIitmaWxlKyIgIitpYm0pOwoJCQlyZXR1cm4gaWJtOwoJCX0KCgkJQE92ZXJyaWRlCgkJcHVibGljIGJvb2xlYW4gaXNTYW1lRmlsZShGaWxlT2JqZWN0IGEsIEZpbGVPYmplY3QgYikgewoJCQl0aHJvdyBuZXcgRXJyb3IoKTsKCQl9CgoJCUBPdmVycmlkZQoJCXB1YmxpYyBib29sZWFuIGhhbmRsZU9wdGlvbihTdHJpbmcgY3VycmVudCwgSXRlcmF0b3I8U3RyaW5nPiByZW1haW5pbmcpIHsKCQkJYm9vbGVhbiBobz1qZm0uaGFuZGxlT3B0aW9uKGN1cnJlbnQsIHJlbWFpbmluZyk7CgkJCVN5c3RlbS5vdXQucHJpbnRsbigiaGFuZGxlT3B0aW9uICIrY3VycmVudCsiIC4uLiIpOwoJCQlyZXR1cm4gaG87CgkJfQoKCQlAT3ZlcnJpZGUKCQlwdWJsaWMgYm9vbGVhbiBoYXNMb2NhdGlvbihMb2NhdGlvbiBsb2NhdGlvbikgewoJCQlib29sZWFuIGhsPWpmbS5oYXNMb2NhdGlvbihsb2NhdGlvbik7Ci8vCQkJU3lzdGVtLm91dC5wcmludGxuKCJoYXNMb2NhdGlvbiAiK2xvY2F0aW9uKyIgIitobCk7CgkJCXJldHVybiBobDsKCQl9CgoJCUBPdmVycmlkZQoJCXB1YmxpYyBKYXZhRmlsZU9iamVjdCBnZXRKYXZhRmlsZUZvcklucHV0KExvY2F0aW9uIGxvY2F0aW9uLCBTdHJpbmcgY2xhc3NOYW1lLCBLaW5kIGtpbmQpIHRocm93cyBJT0V4Y2VwdGlvbiB7Ci8vCQkJU3lzdGVtLm91dC5wcmludGxuKCJnZXRKYXZhRmlsZUZvcklucHV0ICIrbG9jYXRpb24rIiAiK2NsYXNzTmFtZSsiICIra2luZC5uYW1lKCkpOwoJCQlyZXR1cm4gamZtLmdldEphdmFGaWxlRm9ySW5wdXQobG9jYXRpb24sIGNsYXNzTmFtZSwga2luZCk7CgkJfQoKCQlAT3ZlcnJpZGUKCQlwdWJsaWMgSmF2YUZpbGVPYmplY3QgZ2V0SmF2YUZpbGVGb3JPdXRwdXQoTG9jYXRpb24gbG9jYXRpb24sIFN0cmluZyBjbGFzc05hbWUsIEtpbmQga2luZCwgRmlsZU9iamVjdCBzaWJsaW5nKQoJCQkJdGhyb3dzIElPRXhjZXB0aW9uIHsKCQkJU3lzdGVtLm91dC5wcmludGxuKCJnZXRKYXZhRmlsZUZvck91dHB1dCAiK2xvY2F0aW9uKyIgIitjbGFzc05hbWUrIiAiK2tpbmQubmFtZSgpKyIgIitzaWJsaW5nKTsKCQkJaWYoZmlsZXMuY29udGFpbnNLZXkoY2xhc3NOYW1lKSkKCQkJCXRocm93IG5ldyBFcnJvcigpOwoJCQlKRk8gamZvPW5ldyBKRk8oY2xhc3NOYW1lLG51bGwpOwoJCQlmaWxlcy5wdXQoY2xhc3NOYW1lLCBqZm8pOwoJCQlyZXR1cm4gamZvOwoJCX0KCgkJQE92ZXJyaWRlCgkJcHVibGljIEZpbGVPYmplY3QgZ2V0RmlsZUZvcklucHV0KExvY2F0aW9uIGxvY2F0aW9uLCBTdHJpbmcgcGFja2FnZU5hbWUsIFN0cmluZyByZWxhdGl2ZU5hbWUpCgkJCQl0aHJvd3MgSU9FeGNlcHRpb24gewoJCQl0aHJvdyBuZXcgRXJyb3IoKTsKCQl9CgoJCUBPdmVycmlkZQoJCXB1YmxpYyBGaWxlT2JqZWN0IGdldEZpbGVGb3JPdXRwdXQoTG9jYXRpb24gbG9jYXRpb24sIFN0cmluZyBwYWNrYWdlTmFtZSwgU3RyaW5nIHJlbGF0aXZlTmFtZSwKCQkJCUZpbGVPYmplY3Qgc2libGluZykgdGhyb3dzIElPRXhjZXB0aW9uIHsKCQkJdGhyb3cgbmV3IEVycm9yKCk7CgkJfQoKCQlAT3ZlcnJpZGUKCQlwdWJsaWMgdm9pZCBmbHVzaCgpIHRocm93cyBJT0V4Y2VwdGlvbiB7CgkJCVN5c3RlbS5vdXQucHJpbnRsbigiZmx1c2giKTsKCQl9CgoJCUBPdmVycmlkZQoJCXB1YmxpYyB2b2lkIGNsb3NlKCkgdGhyb3dzIElPRXhjZXB0aW9uIHsKCQkJdGhyb3cgbmV3IEVycm9yKCk7CgkJfQoJCQoJICAgIHB1YmxpYyBMb2NhdGlvbiBnZXRMb2NhdGlvbkZvck1vZHVsZShMb2NhdGlvbiBsb2NhdGlvbiwgU3RyaW5nIG1vZHVsZU5hbWUpIHRocm93cyBJT0V4Y2VwdGlvbiB7CgkgICAgICAgIHRocm93IG5ldyBVbnN1cHBvcnRlZE9wZXJhdGlvbkV4Y2VwdGlvbigpOwoJICAgIH0KCgkgICAgcHVibGljIExvY2F0aW9uIGdldExvY2F0aW9uRm9yTW9kdWxlKExvY2F0aW9uIGxvY2F0aW9uLCBKYXZhRmlsZU9iamVjdCBmbykgdGhyb3dzIElPRXhjZXB0aW9uIHsKCSAgICAgICAgdGhyb3cgbmV3IFVuc3VwcG9ydGVkT3BlcmF0aW9uRXhjZXB0aW9uKCk7CgkgICAgfQoKCSAgICBwdWJsaWMgPFM+IFNlcnZpY2VMb2FkZXI8Uz4gZ2V0U2VydmljZUxvYWRlcihMb2NhdGlvbiBsb2NhdGlvbiwgQ2xhc3M8Uz4gc2VydmljZSkgdGhyb3dzICBJT0V4Y2VwdGlvbiB7CgkgICAgICAgIHRocm93IG5ldyBVbnN1cHBvcnRlZE9wZXJhdGlvbkV4Y2VwdGlvbigpOwoJICAgIH0KCgkgICAgcHVibGljIFN0cmluZyBpbmZlck1vZHVsZU5hbWUoTG9jYXRpb24gbG9jYXRpb24pIHRocm93cyBJT0V4Y2VwdGlvbiB7CgkgICAgCVN0cmluZyBpbW09amZtLmluZmVyTW9kdWxlTmFtZShsb2NhdGlvbik7Ci8vCSAgICAJU3lzdGVtLm91dC5wcmludGxuKCJpbmZlck1vZHVsZU5hbWUgIitsb2NhdGlvbisiICIraW1tKTsKCSAgICAJcmV0dXJuIGltbTsKCSAgICB9CgoJICAgIHB1YmxpYyBJdGVyYWJsZTxTZXQ8TG9jYXRpb24+PiBsaXN0TG9jYXRpb25zRm9yTW9kdWxlcyhMb2NhdGlvbiBsb2NhdGlvbikgdGhyb3dzIElPRXhjZXB0aW9uIHsKCSAgICAJSXRlcmFibGU8U2V0PExvY2F0aW9uPj4gbGxmbT1qZm0ubGlzdExvY2F0aW9uc0Zvck1vZHVsZXMobG9jYXRpb24pOwoJICAgIAlTeXN0ZW0ub3V0LnByaW50bG4oImxpc3RMb2NhdGlvbnNGb3JNb2R1bGVzICIrbG9jYXRpb24rIiAuLi4iKTsKCSAgICAJcmV0dXJuIGxsZm07CgkgICAgfQoKCSAgICBwdWJsaWMgYm9vbGVhbiBjb250YWlucyhMb2NhdGlvbiBsb2NhdGlvbiwgRmlsZU9iamVjdCBmbykgdGhyb3dzIElPRXhjZXB0aW9uIHsKCSAgICAgICAgdGhyb3cgbmV3IFVuc3VwcG9ydGVkT3BlcmF0aW9uRXhjZXB0aW9uKCk7CgkgICAgfQoJfQoJCglzdGF0aWMgY2xhc3MgQ0wgZXh0ZW5kcyBDbGFzc0xvYWRlciB7CgkJcHVibGljIENsYXNzPD8+IGRlZmluZUNsYXNzKFN0cmluZyBuYW1lLGJ5dGUgYXJyYXlbXSkgewoJCQlyZXR1cm4gZGVmaW5lQ2xhc3MobmFtZSwgYXJyYXksIDAsIGFycmF5Lmxlbmd0aCk7CgkJfQoJfQp9Cg==