ebcdc1c785937fdd92a3c23812510b945224dffc
[nestedvm.git] / src / org / ibex / nestedvm / util / Platform.java
1 // Copyright 2000-2005 the Contributors, as shown in the revision logs.
2 // Licensed under the Apache Public Source License 2.0 ("the License").
3 // You may not use this file except in compliance with the License.
4
5 package org.ibex.nestedvm.util;
6
7 import java.io.*;
8 import java.nio.channels.*;
9 import java.net.*;
10 import java.util.*;
11
12 import java.text.DateFormatSymbols;
13
14 /*
15  GCCLASS_HINT: org.ibex.nestedvm.util.Platform.<clinit> org.ibex.nestedvm.util.Platform$Jdk11.<init>
16  GCCLASS_HINT: org.ibex.nestedvm.util.Platform.<clinit> org.ibex.nestedvm.util.Platform$Jdk12.<init>
17  GCCLASS_HINT: org.ibex.nestedvm.util.Platform.<clinit> org.ibex.nestedvm.util.Platform$Jdk13.<init>
18  GCCLASS_HINT: org.ibex.nestedvm.util.Platform.<clinit> org.ibex.nestedvm.util.Platform$Jdk14.<init>
19 */
20
21 public abstract class Platform {
22     Platform() { }
23     private static final Platform p;
24     
25     static {
26         float version;
27         try {
28             if(getProperty("java.vm.name").equals("SableVM"))
29                 version = 1.2f;
30             else
31                 version = Float.valueOf(getProperty("java.specification.version")).floatValue();
32         } catch(Exception e) {
33             System.err.println("WARNING: " + e + " while trying to find jvm version -  assuming 1.1");
34             version = 1.1f;
35         }
36         String platformClass;
37         if(version >= 1.4f) platformClass = "Jdk14";
38         else if(version >= 1.3f) platformClass = "Jdk13";
39         else if(version >= 1.2f) platformClass = "Jdk12";
40         else if(version >= 1.1f) platformClass = "Jdk11";
41         else throw new Error("JVM Specification version: " + version + " is too old. (see org.ibex.util.Platform to add support)");
42         
43         try {
44             p = (Platform) Class.forName(Platform.class.getName() + "$" + platformClass).newInstance();
45         } catch(Exception e) {
46             e.printStackTrace();
47             throw new Error("Error instansiating platform class");
48         }
49     }
50     
51     public static String getProperty(String key) {
52         try {
53             return System.getProperty(key);
54         } catch(SecurityException e) {
55             return null;
56         }
57     }
58     
59     
60     abstract boolean _atomicCreateFile(File f) throws IOException;
61     public static boolean atomicCreateFile(File f) throws IOException { return p._atomicCreateFile(f); }
62
63     abstract Seekable.Lock _lockFile(Seekable s, RandomAccessFile raf, long pos, long size, boolean shared) throws IOException;
64     public static Seekable.Lock lockFile(Seekable s, RandomAccessFile raf, long pos, long size, boolean shared) throws IOException {
65         return p._lockFile(s, raf, pos, size, shared); }
66     
67     abstract void _socketHalfClose(Socket s, boolean output) throws IOException;
68     public static void socketHalfClose(Socket s, boolean output) throws IOException { p._socketHalfClose(s,output); }
69     
70     abstract void _socketSetKeepAlive(Socket s, boolean on) throws SocketException;
71     public static void socketSetKeepAlive(Socket s, boolean on) throws SocketException { p._socketSetKeepAlive(s,on); }
72     
73     abstract InetAddress _inetAddressFromBytes(byte[] a) throws UnknownHostException;
74     public static InetAddress inetAddressFromBytes(byte[] a) throws UnknownHostException { return p._inetAddressFromBytes(a); }
75     
76     abstract String _timeZoneGetDisplayName(TimeZone tz, boolean dst, boolean showlong, Locale l);
77     public static String timeZoneGetDisplayName(TimeZone tz, boolean dst, boolean showlong, Locale l) { return p._timeZoneGetDisplayName(tz,dst,showlong,l); }
78     public static String timeZoneGetDisplayName(TimeZone tz, boolean dst, boolean showlong) { return timeZoneGetDisplayName(tz,dst,showlong,Locale.getDefault()); }
79
80     abstract void _setFileLength(RandomAccessFile f, int length)
81         throws IOException;
82     public static void setFileLength(RandomAccessFile f, int length)
83         throws IOException { p._setFileLength(f, length); }
84     
85     abstract File[] _listRoots();
86     public static File[] listRoots() { return p._listRoots(); }
87     
88     abstract File _getRoot(File f);
89     public static File getRoot(File f) { return p._getRoot(f); }
90     
91     static class Jdk11 extends Platform {
92         boolean _atomicCreateFile(File f) throws IOException {
93             // This is not atomic, but its the best we can do on jdk 1.1
94             if(f.exists()) return false;
95             new FileOutputStream(f).close();
96             return true;
97         }
98         Seekable.Lock _lockFile(Seekable s, RandomAccessFile raf, long p, long size, boolean shared) throws IOException {
99             throw new IOException("file locking requires jdk 1.4+");
100         }
101         void _socketHalfClose(Socket s, boolean output) throws IOException {
102             throw new IOException("half closing sockets not supported");
103         }
104         InetAddress _inetAddressFromBytes(byte[] a) throws UnknownHostException {
105             if(a.length != 4) throw new UnknownHostException("only ipv4 addrs supported");
106             return InetAddress.getByName(""+(a[0]&0xff)+"."+(a[1]&0xff)+"."+(a[2]&0xff)+"."+(a[3]&0xff));
107         }
108         void _socketSetKeepAlive(Socket s, boolean on) throws SocketException {
109             if(on) throw new SocketException("keepalive not supported");
110         }
111         String _timeZoneGetDisplayName(TimeZone tz, boolean dst, boolean showlong, Locale l) {
112             String[][] zs  = new DateFormatSymbols(l).getZoneStrings();
113             String id = tz.getID();
114             for(int i=0;i<zs.length;i++)
115                 if(zs[i][0].equals(id))
116                     return zs[i][dst ? (showlong ? 3 : 4) : (showlong ? 1 : 2)];
117             StringBuffer sb = new StringBuffer("GMT");
118             int off = tz.getRawOffset() / 1000;
119             if(off < 0) { sb.append("-"); off = -off; }
120             else sb.append("+");
121             sb.append(off/3600); off = off%3600;
122             if(off > 0) sb.append(":").append(off/60); off=off%60;
123             if(off > 0) sb.append(":").append(off);
124             return sb.toString();
125         }
126
127         void _setFileLength(RandomAccessFile f, int length) throws IOException{
128             InputStream in = new FileInputStream(f.getFD());
129             OutputStream out = new FileOutputStream(f.getFD());
130
131             byte[] buf = new byte[1024];
132             for (int len; length > 0; length -= len) {
133                 len = in.read(buf, 0, Math.min(length, buf.length));
134                 if (len == -1) break;
135                 out.write(buf, 0, len);
136             }
137             if (length == 0) return;
138
139             // fill the rest of the space with zeros
140             for (int i=0; i < buf.length; i++) buf[i] = 0;
141             while (length > 0) {
142                 out.write(buf, 0, Math.min(length, buf.length));
143                 length -= buf.length;
144             }
145         }
146
147         RandomAccessFile _truncatedRandomAccessFile(File f, String mode) throws IOException {
148             new FileOutputStream(f).close();
149             return new RandomAccessFile(f,mode);
150         }
151         
152         File[] _listRoots() {
153             String[] rootProps = new String[]{"java.home","java.class.path","java.library.path","java.io.tmpdir","java.ext.dirs","user.home","user.dir" };
154             Hashtable known = new Hashtable();
155             for(int i=0;i<rootProps.length;i++) {
156                 String prop = getProperty(rootProps[i]);
157                 if(prop == null) continue;
158                 for(;;) {
159                     String path = prop;
160                     int p;
161                     if((p = prop.indexOf(File.pathSeparatorChar)) != -1) {
162                         path = prop.substring(0,p);
163                         prop = prop.substring(p+1);
164                     }
165                     File root = getRoot(new File(path));
166                     //System.err.println(rootProps[i] + ": " + path + " -> " + root);
167                     known.put(root,Boolean.TRUE);
168                     if(p == -1) break;
169                 }
170             }
171             File[] ret = new File[known.size()];
172             int i=0;
173             for(Enumeration e = known.keys();e.hasMoreElements();)
174                 ret[i++] = (File) e.nextElement();
175             return ret;
176         }
177         
178         File _getRoot(File f) {
179             if(!f.isAbsolute()) f = new File(f.getAbsolutePath());
180             String p;
181             while((p = f.getParent()) != null) f = new File(p);
182             if(f.getPath().length() == 0) f = new File("/"); // work around a classpath bug
183             return f;
184         }
185     }
186     
187     static class Jdk12 extends Jdk11 {
188         boolean _atomicCreateFile(File f) throws IOException {
189             return f.createNewFile();
190         }
191         
192         String _timeZoneGetDisplayName(TimeZone tz, boolean dst, boolean showlong, Locale l) {
193             return tz.getDisplayName(dst,showlong ? TimeZone.LONG : TimeZone.SHORT, l);
194         }
195
196         void _setFileLength(RandomAccessFile f, int length) throws IOException {
197             f.setLength(length);
198         }
199
200         File[] _listRoots() { return File.listRoots(); }
201     }
202     
203     static class Jdk13 extends Jdk12 {
204         void _socketHalfClose(Socket s, boolean output) throws IOException {
205             if(output) s.shutdownOutput();
206             else s.shutdownInput();
207         }
208         
209         void _socketSetKeepAlive(Socket s, boolean on) throws SocketException {
210             s.setKeepAlive(on);
211         }
212     }
213     
214     static class Jdk14 extends Jdk13 {
215         InetAddress _inetAddressFromBytes(byte[] a) throws UnknownHostException { return InetAddress.getByAddress(a); } 
216
217         Seekable.Lock _lockFile(Seekable s, RandomAccessFile r, long pos, long size, boolean shared) throws IOException {
218             FileLock flock;
219             try {
220                 flock = pos == 0 && size == 0 ? r.getChannel().lock() :
221                     r.getChannel().tryLock(pos, size, shared);
222             } catch (OverlappingFileLockException e) { flock = null; }
223             if (flock == null) return null; // region already locked
224             return new Jdk14FileLock(s, flock);
225         }
226     }
227
228     private static final class Jdk14FileLock extends Seekable.Lock {
229         private final Seekable s;
230         private final FileLock l;
231
232         Jdk14FileLock(Seekable sk, FileLock flock) { s = sk; l = flock; }
233         public Seekable seekable() { return s; }
234         public boolean isShared() { return l.isShared(); }
235         public boolean isValid() { return l.isValid(); }
236         public void release() throws IOException { l.release(); }
237         public long position() { return l.position(); }
238         public long size() { return l.size(); }
239         public String toString() { return l.toString(); }
240     }
241 }