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==