package php.runtime.ext.support; import php.runtime.Information; import php.runtime.Startup; import php.runtime.annotation.Reflection; import php.runtime.common.collections.map.HashedMap; import php.runtime.env.CompileScope; import php.runtime.env.Environment; import php.runtime.exceptions.CriticalException; import php.runtime.ext.java.JavaException; import php.runtime.ext.support.compile.*; import php.runtime.lang.BaseWrapper; import php.runtime.lang.IObject; import php.runtime.memory.support.MemoryOperation; import java.util.LinkedHashMap; import java.util.Map; abstract public class Extension { public enum Status { EXPERIMENTAL, BETA, STABLE, LEGACY, ZEND_LEGACY, DEPRECATED } public interface Extensible { Extension getExtension(); } protected final Map<String, CompileConstant> constants = new LinkedHashMap<>(); protected final Map<String, CompileFunctionSpec> functions = new LinkedHashMap<>(); protected final Map<String, Class<?>> classes = new LinkedHashMap<>(); public String getName() { return getClass().getName(); } public String[] getPackageNames() { return new String[0]; } public String getVersion() { return Information.CORE_VERSION; } abstract public Status getStatus(); @Deprecated public String[] getRequiredExtensions(){ return new String[0]; } @Deprecated public String[] getOptionalExtensions(){ return new String[0]; } @Deprecated public String[] getConflictExtensions(){ return new String[0]; } public Map<String, String> getINIEntries(){ return new HashedMap<>(); } abstract public void onRegister(CompileScope scope); public void onLoad(Environment env){ // nop } public Map<String, CompileConstant> getConstants() { return constants; } public Map<String, CompileFunctionSpec> getFunctions() { return functions; } public Map<String, Class<?>> getClasses() { return classes; } @Deprecated public void registerNativeClass(CompileScope scope, Class<?> clazz) { registerClass(scope, clazz); } public void registerClass(CompileScope scope, Class<?> clazz) { if (BaseWrapper.class.isAssignableFrom(clazz) && !clazz.isAnnotationPresent(Reflection.NotWrapper.class)) { throw new CriticalException("Please use registerWrapperClass() method instead of this for wrapper classes"); } if (classes.put(clazz.getName(), clazz) != null) throw new CriticalException("Class already registered - " + clazz.getName()); } public <T> void registerWrapperClass(CompileScope scope, Class<T> clazz, Class<? extends BaseWrapper> wrapperClass) { if (classes.put(clazz.getName(), wrapperClass) != null) throw new CriticalException("Class already registered - " + clazz.getName()); MemoryOperation.registerWrapper(clazz, wrapperClass); } public void registerMemoryOperation(Class<? extends MemoryOperation> clazz) { try { MemoryOperation.register(clazz.newInstance()); } catch (InstantiationException | IllegalAccessException e) { throw new CriticalException(e); } } @SuppressWarnings("unchecked") public void registerJavaException(CompileScope scope, Class<? extends JavaException> javaClass, Class<? extends Throwable>... classes) { registerClass(scope, javaClass); if (classes != null) for(Class<? extends Throwable> el : classes) scope.registerJavaException(javaClass, el); } public void registerJavaExceptionForContext(CompileScope scope, Class<? extends JavaException> javaClass, Class<? extends IObject> context) { registerClass(scope, javaClass); scope.registerJavaExceptionForContext(javaClass, context); } public void registerConstants(ConstantsContainer container){ for(CompileConstant constant : container.getConstants()){ constants.put(constant.name, constant); } } public void registerFunctions(FunctionsContainer container){ for(CompileFunctionSpec function : container.getFunctionSpecs()){ functions.put(function.getLowerName(), function); } } }