svn commit: rev 21120 - in avalon/trunk/tools/magic: artifact/src/dist clean/src/dist engine/src/java/org/apache/avalon/magic jar/src/dist prepare/src/dist test xdoc/src/dist

[email protected]
Newsgroups gmane.comp.jakarta.avalon.cvs
Message-ID <[email protected]>
Author: niclas
Date: Sat Jun 12 01:00:57 2004
New Revision: 21120

Modified:
   avalon/trunk/tools/magic/artifact/src/dist/magic.bsh
   avalon/trunk/tools/magic/clean/src/dist/magic.bsh
   avalon/trunk/tools/magic/engine/src/java/org/apache/avalon/magic/Artifact.java
   avalon/trunk/tools/magic/engine/src/java/org/apache/avalon/magic/PluginContext.java
   avalon/trunk/tools/magic/engine/src/java/org/apache/avalon/magic/PluginProperties.java
   avalon/trunk/tools/magic/engine/src/java/org/apache/avalon/magic/ScriptFacade.java
   avalon/trunk/tools/magic/jar/src/dist/magic.bsh
   avalon/trunk/tools/magic/jar/src/dist/magic.properties
   avalon/trunk/tools/magic/prepare/src/dist/magic.bsh
   avalon/trunk/tools/magic/prepare/src/dist/magic.properties
   avalon/trunk/tools/magic/test/magic.properties
   avalon/trunk/tools/magic/xdoc/src/dist/magic.bsh
   avalon/trunk/tools/magic/xdoc/src/dist/magic.properties
Log:
Need to commit to continue with changes.

Modified: avalon/trunk/tools/magic/artifact/src/dist/magic.bsh
==============================================================================
--- avalon/trunk/tools/magic/artifact/src/dist/magic.bsh	(original)
+++ avalon/trunk/tools/magic/artifact/src/dist/magic.bsh	Sat Jun 12 01:00:57 2004
@@ -15,20 +15,23 @@
 limitations under the License.
 */
 
-import com.jcraft.jsch.ChannelExec;
-import com.jcraft.jsch.Session;
-
 import java.io.File;
 import java.io.FileInputStream;
+import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+
+import java.text.SimpleDateFormat;
 
-import java.util.LinkedList;
-import java.util.List;
+import java.util.Date;
+import java.util.TimeZone;
 
 import org.apache.avalon.magic.AbstractPlugin;
 import org.apache.avalon.magic.Artifact;
+import org.apache.avalon.magic.ArtifactException;
 
 import org.apache.avalon.framework.service.Serviceable;
 import org.apache.avalon.framework.service.ServiceException;
@@ -73,6 +76,7 @@
             File dest = artifact.toLocalFile();
             PreparePlugin prepare = (PreparePlugin) m_PreparePlugin;
             prepare.copyFile( content, dest );
+            metagen( artifact );
         } catch( Exception e )
         {
             e.printStackTrace();
@@ -97,6 +101,115 @@
         //        which probably happens with Ant filesets.
         source = source + ".md5";
         upload( source, fullDest );
+    }
+    
+    public void metagen( Artifact artifact )
+        throws IOException, ArtifactException
+    {
+        File artifactFile = artifact.toLocalFile();
+        String artifactFilename = artifactFile.getAbsolutePath();
+
+        File metaFile = new File( artifactFilename + ".meta" );
+
+        SimpleDateFormat sdf = new SimpleDateFormat( "yyyyMMdd.HHmmss" );
+        sdf.setTimeZone( TimeZone.getTimeZone("UTC") );
+        Date created = new Date( artifactFile.lastModified() );
+        String signature = sdf.format( created );
+        FileOutputStream fos = new FileOutputStream( metaFile );
+        OutputStreamWriter out = new OutputStreamWriter( fos, "ISO8859-1" );
+        PrintWriter writer = new PrintWriter( out );
+        
+        writer.println();
+        writer.println( "#" );
+        writer.println( "# Meta classifier." );
+        writer.println( "# " );
+
+        writer.println( "meta.domain = avalon" );
+        writer.println( "meta.version = 1.1" );
+
+        writer.println();
+        writer.println( "#" );
+        writer.println( "# Artifact descriptor." );
+        writer.println( "# " );
+        writer.print( "avalon.artifact.group = " );
+        writer.println( artifact.getGroupId() );
+        writer.print( "avalon.artifact.name = " );
+        writer.println( artifact.getArtifactId() );
+        writer.print( "avalon.artifact.version = " );
+        writer.println( artifact.getVersion() );
+        writer.print( "avalon.artifact.signature = " );
+        writer.println( signature );
+        
+        Artifact[] deps = artifact.getDependencies();
+        writeDeps( writer, deps, "api" );
+        writeDeps( writer, deps, "spi" );
+        writeDeps( writer, deps, "" );
+        
+        String factory = m_Context.getProperty( "avalon.artifact.factory" );
+        if( factory != null && ! "".equals( factory ) )
+        {
+            writer.println();
+            writer.println( "#" );
+            writer.println( "# Factory classname." );
+            writer.println( "#" );
+
+            writer.print( "avalon.artifact.factory = " );
+            writer.println( factory );
+        }
+        
+        String export = m_Context.getProperty( "avalon.artifact.export" );
+        if( export != null && ! "".equals( export ) )
+        {
+            writer.println();
+            writer.println( "#" );
+            writer.println( "# Service export." );
+            writer.println( "#" );
+
+            writer.print( "avalon.artifact.export = " );
+            writer.println( export );
+        }
+        writer.println();
+        writer.println( "#" );
+        writer.println( "# EOF" );
+        writer.println( "#" );
+        
+        writer.close();
+        out.close();
+        fos.close();
+    }
+
+    private void writeDeps( PrintWriter writer, Artifact[] deps, String type )
+    {
+        int index = 0;
+        for( int i = 0 ; i < deps.length ; i++ )
+        {
+            Artifact dep = deps[i];
+            
+            String clType = dep.getProperty( "avalon.classloader" );
+            if( clType == null )
+                clType = "";
+                
+            if( type.equals( clType ) )
+            {
+                if( index == 0 )
+                {
+                    String t = type.equals( "" ) ? "Impl" : type.toUpperCase();
+                    writer.println();
+                    writer.println( "# " );
+                    writer.println( "# " + t + " Dependencies" );
+                    writer.println( "# " );
+                }
+                String key = dep.toArtifactURL();
+                
+                writer.print( "avalon.artifact.dependency." );
+                writer.print( clType ); 
+                if( ! "".equals( clType ) )
+                    writer.print( "." );
+                writer.print( index++ );
+                writer.print( " = " );
+                writer.println( key );
+            }
+        }
     }
     
     private void upload( String source, String dest )

Modified: avalon/trunk/tools/magic/clean/src/dist/magic.bsh
==============================================================================
--- avalon/trunk/tools/magic/clean/src/dist/magic.bsh	(original)
+++ avalon/trunk/tools/magic/clean/src/dist/magic.bsh	Sat Jun 12 01:00:57 2004
@@ -41,14 +41,33 @@
         throws IOException
     {   
         notifyPreMethod( "clean" );
-        delete();    
+        File basedir = m_Context.getProjectDir();
+        deleteTargets( basedir );    
+        recurse( basedir );
         notifyPostMethod( "clean" );
     }
     
-    private void delete()
+    private void recurse( File basedir )
+        throws IOException
+    {
+        File[] content = basedir.listFiles();
+        for( int i = 0 ; i < content.length ; i++ )
+        {
+            if( content[i].isDirectory() )
+            {
+                File magicFile = new File( content[i], "magic.properties" );
+                if( magicFile.exists() )
+                {
+                    deleteTargets( content[i] );
+                    recurse( content[i] );
+                }
+            }
+        }
+    }
+    
+    private void deleteTargets( File basedir )
         throws IOException
     {
-        File basedir = m_Context.getProjectDir();
         String targets = m_Context.getProperty( "clean.dirs" );
         StringTokenizer st = new StringTokenizer( targets, " ,", false );
         while( st.hasMoreTokens() )

Modified: avalon/trunk/tools/magic/engine/src/java/org/apache/avalon/magic/Artifact.java
==============================================================================
--- avalon/trunk/tools/magic/engine/src/java/org/apache/avalon/magic/Artifact.java	(original)
+++ avalon/trunk/tools/magic/engine/src/java/org/apache/avalon/magic/Artifact.java	Sat Jun 12 01:00:57 2004
@@ -30,8 +30,9 @@
 import java.net.URLConnection;
 
 import java.util.ArrayList;
-import java.util.Properties;
 import java.util.Iterator;
+import java.util.Properties;
+import java.util.StringTokenizer;
 
 public class Artifact
 {
@@ -43,8 +44,9 @@
     private String          m_Version;
     private String          m_Type;
     private PluginContext   m_Context;
+    private Properties      m_Properties;
     
-    private Artifact( PluginContext context, String artifactId, String groupId, String version, String type, String repository )
+    private Artifact( PluginContext context, String artifactId, String groupId, String version, String type, String repository, String properties )
     {
         if( repository == null || "".equals( repository ) )
             repository = DEFAULT_REPOSITORY;
@@ -55,19 +57,28 @@
         m_GroupId = groupId.trim();
         m_Version = version.trim();
         m_Type = type.trim();
+        m_Properties = parseProps( properties );
     }
 
     public static Artifact resolve( PluginContext context, String artifactId )
         throws IOException, ArtifactException
     {
         if( artifactId.startsWith( "artifact:" ) )
-            return resolveDirect( context, artifactId );
+            return resolveDirect( context, artifactId, "" );
         else
-            return resolveIndirect( context, artifactId );
+            return resolveIndirect( context, artifactId, "" );
     }
     
+    public static Artifact resolve( PluginContext context, String artifactId, String properties )
+        throws IOException, ArtifactException
+    {
+        if( artifactId.startsWith( "artifact:" ) )
+            return resolveDirect( context, artifactId, properties );
+        else
+            return resolveIndirect( context, artifactId, properties );
+    }
     
-    private static Artifact resolveDirect( PluginContext context, String artifactId )
+    private static Artifact resolveDirect( PluginContext context, String artifactId, String properties )
         throws IOException, ArtifactException
     {
         String id = artifactId;
@@ -96,11 +107,11 @@
         }
         String repository = context.getProperty( "artifact.repository" );
         
-        Artifact artifact = new Artifact( context, name, group, version, type, repository );
+        Artifact artifact = new Artifact( context, name, group, version, type, repository, properties );
         return artifact;
     }
     
-    private static Artifact resolveIndirect( PluginContext context, String artifactId )
+    private static Artifact resolveIndirect( PluginContext context, String artifactId, String properties )
         throws IOException
     {
         File definitionsDir = new File( context.getProjectSystemDir(), "definitions" );
@@ -135,7 +146,13 @@
         if( type == null )
             type = "jar";
 
-        Artifact artifact = new Artifact( context, artifactId, groupId, version, type, repository );
+        String props = p.getProperty( "artifact.properties" );
+        if( props == null )
+            props = "";
+        if( properties != null && ! "".equals( properties ))
+            props = props + "," + properties;  // override with explicit properties given.
+        
+        Artifact artifact = new Artifact( context, artifactId, groupId, version, type, repository, props );
         return artifact;
     }
     
@@ -181,7 +198,14 @@
         for( int i=0 ; list.hasNext() ; i++ )
         {
             String dep = (String) list.next();
-            result[i] = resolve( m_Context, dep );
+            int pos = dep.indexOf( " " );
+            String props = "";
+            if( pos >= 0 )
+            {
+                props = dep.substring( pos + 1 );
+                dep = dep.substring( 0, pos );
+            }
+            result[i] = resolve( m_Context, dep, props );
         }
         return result;
     }
@@ -248,6 +272,11 @@
         return localFile;
     }
     
+    public String toArtifactURL()
+    {
+        return "artifact:" + m_Type + ":" + m_GroupId + "/" + m_ArtifactId + "#" + m_Version;
+    }
+    
     public File getContentFile()
         throws IOException
     {
@@ -258,5 +287,33 @@
             Util.download( this, localfile );
         }
         return localfile;
+    }
+    
+    private Properties parseProps( String props ) 
+    {
+        Properties result = new Properties();
+        if( props != null )
+        {
+            StringTokenizer st = new StringTokenizer( props, ";", false );
+            while( st.hasMoreTokens() )
+            {
+                String pair = st.nextToken().trim();
+                int pos = pair.indexOf( "=" );
+                if( pos < 0 )
+                    result.put( pair, "" );
+                else
+                {
+                    String key = pair.substring( 0, pos );
+                    String value = pair.substring( pos + 1 );
+                    result.put( key, value );
+                }
+            }
+        }
+        return result;
+    }
+    
+    public String getProperty( String key )
+    {
+        return m_Properties.getProperty( key );
     }
 } 

Modified: avalon/trunk/tools/magic/engine/src/java/org/apache/avalon/magic/PluginContext.java
==============================================================================
--- avalon/trunk/tools/magic/engine/src/java/org/apache/avalon/magic/PluginContext.java	(original)
+++ avalon/trunk/tools/magic/engine/src/java/org/apache/avalon/magic/PluginContext.java	Sat Jun 12 01:00:57 2004
@@ -163,7 +163,21 @@
     public String getProperty( String name )
     {
         String value = m_ProjectProperties.getProperty( name );
+        if( value == null )
+        {
+            if( name.equals( "plugin.dir" ) )
+                return m_PluginDir.getAbsolutePath();
+            if( name.equals( "system.dir" ) )
+                return m_SystemDir.getAbsolutePath();
+            if( name.equals( "temp.dir" ) )
+                return m_TempDir.getAbsolutePath();
+        }
         return value;
+    }
+    
+    public void setProperty( String name, String value )
+    {
+        m_ProjectProperties.setProperty( name, value );
     }
     
     public Iterator getPropertyKeys()

Modified: avalon/trunk/tools/magic/engine/src/java/org/apache/avalon/magic/PluginProperties.java
==============================================================================
--- avalon/trunk/tools/magic/engine/src/java/org/apache/avalon/magic/PluginProperties.java	(original)
+++ avalon/trunk/tools/magic/engine/src/java/org/apache/avalon/magic/PluginProperties.java	Sat Jun 12 01:00:57 2004
@@ -25,11 +25,11 @@
 
 public class PluginProperties extends Properties
 {
-    public PluginProperties()
+    PluginProperties()
     {
     }
     
-    public PluginProperties( Properties content )
+    PluginProperties( Properties content )
     {
         super();
         Iterator list = content.entrySet().iterator();
@@ -42,82 +42,24 @@
         }
     }
     
-    public String getProperty( String name )
+    public String getProperty( String name, PropertyResolver resolver )
     {
         name = name.trim();
         String value = super.getProperty( name );
         if( value == null )
             return null;
         value = value.trim();
-        return resolve( value );
+        return resolver.resolve( value );
     }
     
-    public String resolve( String value )
+    public String getProperty( String name )
     {
-        // optimization for common case.
-        int pos1 = value.indexOf( "${" );
-        if( pos1 < 0 )
-            return value;
-        
-        Stack stack = new Stack();
-        StringTokenizer st = new StringTokenizer( value, "${}", true );
-        
-        while( st.hasMoreTokens() )
-        {
-            String token = st.nextToken();
-            if( token.equals( "}" ) )
-            {
-                String name = (String) stack.pop();
-                String open = (String) stack.pop();
-                if( open.equals( "${" ) )
-                {
-                    String propValue = getProperty( name );
-                    if( propValue == null )
-                        push( stack, "${" + name + "}" );
-                    else
-                        push( stack, propValue );
-                }
-                else
-                {
-                    push( stack, "${" + name + "}" );
-                }
-            }
-            else
-            {
-                if( token.equals( "$" ) )
-                    stack.push( "$" );
-                else
-                {
-                    push( stack, token );
-                }
-            }
-        }
-        String result = "";
-        while( stack.size() > 0 )
-        {
-            result = (String) stack.pop() + result;
-        }
-        return result;
+        name = name.trim();
+        String value = super.getProperty( name );
+        if( value == null )
+            return null;
+        value = value.trim();
+        return resolve( value );
     }
     
-    private void push( Stack stack , String value )
-    {
-        if( stack.size() > 0 )
-        {
-            String data = (String) stack.pop();
-            if( data.equals( "${" ) )
-            {
-                stack.push( data );
-                stack.push( value );
-            }
-            else
-            {
-                stack.push( data + value );
-            }
-        }
-        else
-        {
-            stack.push( value );
-        }
-    }
-}
+}
\ No newline at end of file

Modified: avalon/trunk/tools/magic/engine/src/java/org/apache/avalon/magic/ScriptFacade.java
==============================================================================
--- avalon/trunk/tools/magic/engine/src/java/org/apache/avalon/magic/ScriptFacade.java	(original)
+++ avalon/trunk/tools/magic/engine/src/java/org/apache/avalon/magic/ScriptFacade.java	Sat Jun 12 01:00:57 2004
@@ -83,19 +83,32 @@
         
         BshClassManager classman = bsh.getClassManager();
         String pluginname = m_Context.getPluginName();
-        Artifact thisArtifact = Artifact.resolve( m_Context, pluginname );
-        System.out.println( thisArtifact );
-        Artifact[] deps = thisArtifact.getDependencies();
-        System.out.println( "Deps: " + deps.length  );
         
-        URL[] urls = Util.getURLs( deps );
-        for( int i = 0 ; i < urls.length ; i++ )
+        // For now, project local build scripts can not have dependencies.
+        if( "".equals( pluginname ) || ".".equals( pluginname) )
         {
-            if( getLogger().isDebugEnabled() )
-                getLogger().debug( "Adding to BeanShell classpath:" + urls[i] );
-            classman.addClassPath( urls[i] );
+        /*
+            Artifact framework = Artifact.resolve( m_Context, "avalon-framework-api" );
+            File file = framework.getContentFile();
+            classman.addClassPath( file.toURL()  );
+        */
         }
-                    
+        else
+        {
+            Artifact thisArtifact = Artifact.resolve( m_Context, pluginname );
+            System.out.println( thisArtifact );
+            Artifact[] deps = thisArtifact.getDependencies();
+            System.out.println( "Deps: " + deps.length  );
+
+            URL[] urls = Util.getURLs( deps );
+            for( int i = 0 ; i < urls.length ; i++ )
+            {
+                if( getLogger().isDebugEnabled() )
+                    getLogger().debug( "Adding to BeanShell classpath:" + urls[i] );
+                classman.addClassPath( urls[i] );
+            }
+        }
+                   
         if( ! classman.classExists( m_Classname ) )
         {
             bsh.eval( m_Script );

Modified: avalon/trunk/tools/magic/jar/src/dist/magic.bsh
==============================================================================
--- avalon/trunk/tools/magic/jar/src/dist/magic.bsh	(original)
+++ avalon/trunk/tools/magic/jar/src/dist/magic.bsh	Sat Jun 12 01:00:57 2004
@@ -79,6 +79,8 @@
             notifyPreMethod( "jar" );
             File manifest = prepareManifest();
             notifyStep( "jar", "manifest-created" );
+            copyResources();
+            notifyStep( "jar", "resources-prepared" );
             createJar( manifest );
             notifyPostMethod( "jar" );
             m_Jarred = true;
@@ -111,7 +113,16 @@
         artplugin.upload( m_CurrentArtifact );
         notifyPostMethod( "upload" );
     }
-    
+
+    private void copyResources()
+    {
+        File toDir = new File( m_Context.getProjectDir(), m_Context.getProperty( "jar.build.src.dir" ) );
+        File fromDir = new File( m_Context.getProjectDir(), m_Context.getProperty( "jar.build.resources.dir" ) );
+        PreparePlugin prepare = (PreparePlugin) m_PreparePlugin;
+        
+        prepare.copy( fromDir, toDir, "**/*", "", false );
+    }
+        
     private File prepareManifest()
     {
         String manifestName = m_Context.getProperty( "jar.manifest" );

Modified: avalon/trunk/tools/magic/jar/src/dist/magic.properties
==============================================================================
--- avalon/trunk/tools/magic/jar/src/dist/magic.properties	(original)
+++ avalon/trunk/tools/magic/jar/src/dist/magic.properties	Sat Jun 12 01:00:57 2004
@@ -1,6 +1,8 @@
 
 jar.build.src.dir = ${java.build.dest.dir}
 
+jar.build.resources.dir = ${prepare.build.src.dir}/resources
+
 jar.build.dest.dir = ${prepare.dest.dir}
 
 jar.manifest = ${prepare.src.dir}/etc/manifest.MF

Modified: avalon/trunk/tools/magic/prepare/src/dist/magic.bsh
==============================================================================
--- avalon/trunk/tools/magic/prepare/src/dist/magic.bsh	(original)
+++ avalon/trunk/tools/magic/prepare/src/dist/magic.bsh	Sat Jun 12 01:00:57 2004
@@ -47,11 +47,29 @@
         if( m_Initialized )
             return;
         notifyPreMethod( "init" );
+        copyLicense();
+        notifyStep( "init", "licensed-copied" );
         copySources();
         notifyPostMethod( "init" );
         m_Initialized = true;
     }
     
+    private void copyLicense()
+    {
+        String licFilename = m_Context.getProperty( "prepare.license.file" );
+        File fromFile;
+        
+        if( licFilename.startsWith( "/" ) )
+            fromFile = new File( licFilename );
+        else
+            fromFile = new File( m_Context.getProjectDir(), licFilename );
+            
+        String destdirname = m_Context.getProperty( "prepare.build.src.dir" );
+        File toDir = new File( m_Context.getProjectDir(), destdirname ); 
+        File toFile = new File( toDir, fromFile.getName() );
+        copyFile( fromFile, toFile );        
+    }
+    
     public void copySources()
     {
         String destdirname = m_Context.getProperty( "prepare.build.src.dir" );
@@ -112,4 +130,4 @@
             fs.addFilter( key, value );
         }
     }
-}   
+}

Modified: avalon/trunk/tools/magic/prepare/src/dist/magic.properties
==============================================================================
--- avalon/trunk/tools/magic/prepare/src/dist/magic.properties	(original)
+++ avalon/trunk/tools/magic/prepare/src/dist/magic.properties	Sat Jun 12 01:00:57 2004
@@ -5,4 +5,6 @@
 
 prepare.build.src.dir = ${prepare.dest.dir}/src/
 
-prepare.filtered.files= **/*.xml, **/*.java, **/*.html, **/*.sh, **/*.bat, **/*.prop*
\ No newline at end of file
+prepare.filtered.files= **/*.xml, **/*.java, **/*.html, **/*.sh, **/*.bat, **/*.prop*
+
+prepare.license.file = ${plugin.dir}/LICENSE.txt
\ No newline at end of file

Modified: avalon/trunk/tools/magic/test/magic.properties
==============================================================================
--- avalon/trunk/tools/magic/test/magic.properties	(original)
+++ avalon/trunk/tools/magic/test/magic.properties	Sat Jun 12 01:00:57 2004
@@ -1,4 +1,4 @@
  
-project.name = test
+project.name = junit
 
 project.system = ../../../central/system

Modified: avalon/trunk/tools/magic/xdoc/src/dist/magic.bsh
==============================================================================
--- avalon/trunk/tools/magic/xdoc/src/dist/magic.bsh	(original)
+++ avalon/trunk/tools/magic/xdoc/src/dist/magic.bsh	Sat Jun 12 01:00:57 2004
@@ -128,6 +128,7 @@
         String srcDir = m_Context.getProperty( "xdoc.build.src.dir" );
         File fromDir = new File( m_Context.getProjectDir(), srcDir );
         File toDir = new File( m_Context.getProjectDir(), m_Context.getProperty( "xdoc.dest.dir" ) );
+        toDir.mkdirs();
         String output = m_Context.getProperty( "xdoc.output.format" );
         String sep = File.separatorChar == '\\' ? "\\\\" : File.separator;
         transformTrax( fromDir, toDir, xslFile, "^.*\\.xml$", "^.*" + sep + "navigation.xml$", "." + output, "html" );
@@ -135,6 +136,8 @@
     
     private void copyResources( File fromDir )
     {
+        if( ! fromDir.exists() )
+            return;
         File destDir = new File( m_Context.getProjectDir(), m_Context.getProperty( "xdoc.dest.dir" ) );
         PreparePlugin prepare = (PreparePlugin) m_PreparePlugin;
         

Modified: avalon/trunk/tools/magic/xdoc/src/dist/magic.properties
==============================================================================
--- avalon/trunk/tools/magic/xdoc/src/dist/magic.properties	(original)
+++ avalon/trunk/tools/magic/xdoc/src/dist/magic.properties	Sat Jun 12 01:00:57 2004
@@ -7,7 +7,7 @@
 
 xdoc.resources.dir = ${prepare.src.dir}/resources/
 
-xdoc.theme.name = avalon2
+xdoc.theme.name = modern
  
 xdoc.output.format=html
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.