001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements.  See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership.  The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the
007     * "License"); you may not use this file except in compliance
008     * with the License.  You may obtain a copy of the License at
009     *
010     *   http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing,
013     * software distributed under the License is distributed on an
014     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015     * KIND, either express or implied.  See the License for the
016     * specific language governing permissions and limitations
017     * under the License.
018     */
019    package org.apache.felix.framework.util;
020    
021    import java.io.*;
022    import java.lang.reflect.*;
023    import java.net.*;
024    import java.security.*;
025    import java.util.HashMap;
026    import java.util.Hashtable;
027    
028    import org.osgi.framework.BundleActivator;
029    import org.osgi.framework.BundleContext;
030    
031    /**
032     * <p>
033     * This is a utility class to centralize all action that should be performed
034     * in a <tt>doPrivileged()</tt> block. To perform a secure action, simply
035     * create an instance of this class and use the specific method to perform
036     * the desired action. When an instance is created, this class will capture
037     * the security context and will then use that context when checking for
038     * permission to perform the action. Instances of this class should not be
039     * passed around since they may grant the receiver a capability to perform
040     * privileged actions.
041     * </p>
042    **/
043    public class SecureAction
044    {
045        private static final ThreadLocal m_actions = new ThreadLocal()
046        {
047            public Object initialValue()
048            {
049                return new Actions();
050            }
051        };
052    
053        protected static transient int BUFSIZE = 4096;
054    
055        private AccessControlContext m_acc = null;
056    
057        public SecureAction()
058        {
059            if (System.getSecurityManager() != null)
060            {
061                try
062                {
063                    Actions actions = (Actions) m_actions.get();
064                    actions.set(Actions.INITIALIZE_CONTEXT, null);
065                    m_acc = (AccessControlContext) AccessController.doPrivileged(actions);
066                }
067                catch (PrivilegedActionException ex)
068                {
069                    throw (RuntimeException) ex.getException();
070                }
071            }
072            else
073            {
074                m_acc = AccessController.getContext();
075            }
076        }
077    
078        public String getSystemProperty(String name, String def)
079        {
080            if (System.getSecurityManager() != null)
081            {
082                try
083                {
084                    Actions actions = (Actions) m_actions.get();
085                    actions.set(Actions.GET_PROPERTY_ACTION, name, def);
086                    return (String) AccessController.doPrivileged(actions, m_acc);
087                }
088                catch (PrivilegedActionException ex)
089                {
090                    throw (RuntimeException) ex.getException();
091                }
092            }
093            else
094            {
095                return System.getProperty(name, def);
096            }
097        }
098    
099        public ClassLoader getParentClassLoader(ClassLoader loader)
100        {
101            if (System.getSecurityManager() != null)
102            {
103                try
104                {
105                    Actions actions = (Actions) m_actions.get();
106                    actions.set(Actions.GET_PARENT_CLASS_LOADER_ACTION, loader);
107                    return (ClassLoader) AccessController.doPrivileged(actions, m_acc);
108                }
109                catch (PrivilegedActionException ex)
110                {
111                    throw (RuntimeException) ex.getException();
112                }
113            }
114            else
115            {
116                return loader.getParent();
117            }
118        }
119    
120        public ClassLoader getSystemClassLoader()
121        {
122            if (System.getSecurityManager() != null)
123            {
124                try
125                {
126                    Actions actions = (Actions) m_actions.get();
127                    actions.set(Actions.GET_SYSTEM_CLASS_LOADER_ACTION);
128                    return (ClassLoader) AccessController.doPrivileged(actions, m_acc);
129                }
130                catch (PrivilegedActionException ex)
131                {
132                    throw (RuntimeException) ex.getException();
133                }
134            }
135            else
136            {
137                return ClassLoader.getSystemClassLoader();
138            }
139        }
140        
141        public ClassLoader getClassLoader(Class clazz)
142        {
143            if (System.getSecurityManager() != null)
144            {
145                try
146                {
147                    Actions actions = (Actions) m_actions.get();
148                    actions.set(Actions.GET_CLASS_LOADER_ACTION, clazz);
149                    return (ClassLoader) AccessController.doPrivileged(actions, m_acc);
150                }
151                catch (PrivilegedActionException ex)
152                {
153                    throw (RuntimeException) ex.getException();
154                }
155            }
156            else
157            {
158                return clazz.getClassLoader();
159            }
160        }
161    
162        public Class forName(String name) throws ClassNotFoundException
163        {
164            if (System.getSecurityManager() != null)
165            {
166                try
167                {
168                    Actions actions = (Actions) m_actions.get();
169                    actions.set(Actions.FOR_NAME_ACTION, name);
170                    return (Class) AccessController.doPrivileged(actions, m_acc);
171                }
172                catch (PrivilegedActionException ex)
173                {
174                    if (ex.getException() instanceof ClassNotFoundException)
175                    {
176                        throw (ClassNotFoundException) ex.getException();
177                    }
178                    throw (RuntimeException) ex.getException();
179                }
180            }
181            else
182            {
183                return Class.forName(name);
184            }
185        }
186    
187        public URL createURL(String protocol, String host,
188            int port, String path, URLStreamHandler handler)
189            throws MalformedURLException
190        {
191            if (System.getSecurityManager() != null)
192            {
193                try
194                {
195                    Actions actions = (Actions) m_actions.get();
196                    actions.set(Actions.CREATE_URL_ACTION, protocol, host,
197                        new Integer(port), path, handler);
198                    return (URL) AccessController.doPrivileged(actions, m_acc);
199                }
200                catch (PrivilegedActionException ex)
201                {
202                    if (ex.getException() instanceof MalformedURLException)
203                    {
204                        throw (MalformedURLException) ex.getException();
205                    }
206                    throw (RuntimeException) ex.getException();
207                }
208            }
209            else
210            {
211                return new URL(protocol, host, port, path, handler);
212            }
213        }
214    
215        public URL createURL(URL context, String spec, URLStreamHandler handler)
216            throws MalformedURLException
217        {
218            if (System.getSecurityManager() != null)
219            {
220                try
221                {
222                    Actions actions = (Actions) m_actions.get();
223                    actions.set(Actions.CREATE_URL_WITH_CONTEXT_ACTION, context,
224                        spec, handler);
225                    return (URL) AccessController.doPrivileged(actions, m_acc);
226                }
227                catch (PrivilegedActionException ex)
228                {
229                    if (ex.getException() instanceof MalformedURLException)
230                    {
231                        throw (MalformedURLException) ex.getException();
232                    }
233                    throw (RuntimeException) ex.getException();
234                }
235            }
236            else
237            {
238                return new URL(context, spec, handler);
239            }
240        }
241    
242        public Process exec(String command) throws IOException
243        {
244            if (System.getSecurityManager() != null)
245            {
246                try
247                {
248                    Actions actions = (Actions) m_actions.get();
249                    actions.set(Actions.EXEC_ACTION, command);
250                    return (Process) AccessController.doPrivileged(actions, m_acc);
251                }
252                catch (PrivilegedActionException ex)
253                {
254                    throw (RuntimeException) ex.getException();
255                }
256            }
257            else
258            {
259                return Runtime.getRuntime().exec(command);
260            }
261        }
262    
263        public String getAbsolutePath(File file)
264        {
265            if (System.getSecurityManager() != null)
266            {
267                try
268                {
269                    Actions actions = (Actions) m_actions.get();
270                    actions.set(Actions.GET_ABSOLUTE_PATH_ACTION, file);
271                    return (String) AccessController.doPrivileged(actions, m_acc);
272                }
273                catch (PrivilegedActionException ex)
274                {
275                    throw (RuntimeException) ex.getException();
276                }
277            }
278            else
279            {
280                return file.getAbsolutePath();
281            }
282        }
283    
284        public boolean fileExists(File file)
285        {
286            if (System.getSecurityManager() != null)
287            {
288                try
289                {
290                    Actions actions = (Actions) m_actions.get();
291                    actions.set(Actions.FILE_EXISTS_ACTION, file);
292                    return ((Boolean) AccessController.doPrivileged(actions, m_acc))
293                        .booleanValue();
294                }
295                catch (PrivilegedActionException ex)
296                {
297                    throw (RuntimeException) ex.getException();
298                }
299            }
300            else
301            {
302                return file.exists();
303            }
304        }
305    
306        public boolean isFileDirectory(File file)
307        {
308            if (System.getSecurityManager() != null)
309            {
310                try
311                {
312                    Actions actions = (Actions) m_actions.get();
313                    actions.set(Actions.FILE_IS_DIRECTORY_ACTION, file);
314                    return ((Boolean) AccessController.doPrivileged(actions, m_acc))
315                        .booleanValue();
316                }
317                catch (PrivilegedActionException ex)
318                {
319                    throw (RuntimeException) ex.getException();
320                }
321            }
322            else
323            {
324                return file.isDirectory();
325            }
326        }
327    
328        public boolean mkdir(File file)
329        {
330            if (System.getSecurityManager() != null)
331            {
332                try
333                {
334                    Actions actions = (Actions) m_actions.get();
335                    actions.set(Actions.MAKE_DIRECTORY_ACTION, file);
336                    return ((Boolean) AccessController.doPrivileged(actions, m_acc))
337                        .booleanValue();
338                }
339                catch (PrivilegedActionException ex)
340                {
341                    throw (RuntimeException) ex.getException();
342                }
343            }
344            else
345            {
346                return file.mkdir();
347            }
348        }
349    
350        public boolean mkdirs(File file)
351        {
352            if (System.getSecurityManager() != null)
353            {
354                try
355                {
356                    Actions actions = (Actions) m_actions.get();
357                    actions.set(Actions.MAKE_DIRECTORIES_ACTION, file);
358                    return ((Boolean) AccessController.doPrivileged(actions, m_acc))
359                        .booleanValue();
360                }
361                catch (PrivilegedActionException ex)
362                {
363                    throw (RuntimeException) ex.getException();
364                }
365            }
366            else
367            {
368                return file.mkdirs();
369            }
370        }
371    
372        public File[] listDirectory(File file)
373        {
374            if (System.getSecurityManager() != null)
375            {
376                try
377                {
378                    Actions actions = (Actions) m_actions.get();
379                    actions.set(Actions.LIST_DIRECTORY_ACTION, file);
380                    return (File[]) AccessController.doPrivileged(actions, m_acc);
381                }
382                catch (PrivilegedActionException ex)
383                {
384                    throw (RuntimeException) ex.getException();
385                }
386            }
387            else
388            {
389                return file.listFiles();
390            }
391        }
392    
393        public boolean renameFile(File oldFile, File newFile)
394        {
395            if (System.getSecurityManager() != null)
396            {
397                try
398                {
399                    Actions actions = (Actions) m_actions.get();
400                    actions.set(Actions.RENAME_FILE_ACTION, oldFile, newFile);
401                    return ((Boolean) AccessController.doPrivileged(actions, m_acc))
402                        .booleanValue();
403                }
404                catch (PrivilegedActionException ex)
405                {
406                    throw (RuntimeException) ex.getException();
407                }
408            }
409            else
410            {
411                return oldFile.renameTo(newFile);
412            }
413        }
414    
415        public InputStream getFileInputStream(File file) throws IOException
416        {
417            if (System.getSecurityManager() != null)
418            {
419                try
420                {
421                    Actions actions = (Actions) m_actions.get();
422                    actions.set(Actions.GET_FILE_INPUT_ACTION, file);
423                    return (InputStream) AccessController.doPrivileged(actions, m_acc);
424                }
425                catch (PrivilegedActionException ex)
426                {
427                    if (ex.getException() instanceof IOException)
428                    {
429                        throw (IOException) ex.getException();
430                    }
431                    throw (RuntimeException) ex.getException();
432                }
433            }
434            else
435            {
436                return new FileInputStream(file);
437            }
438        }
439    
440        public OutputStream getFileOutputStream(File file) throws IOException
441        {
442            if (System.getSecurityManager() != null)
443            {
444                try
445                {
446                    Actions actions = (Actions) m_actions.get();
447                    actions.set(Actions.GET_FILE_OUTPUT_ACTION, file);
448                    return (OutputStream) AccessController.doPrivileged(actions, m_acc);
449                }
450                catch (PrivilegedActionException ex)
451                {
452                    if (ex.getException() instanceof IOException)
453                    {
454                        throw (IOException) ex.getException();
455                    }
456                    throw (RuntimeException) ex.getException();
457                }
458            }
459            else
460            {
461                return new FileOutputStream(file);
462            }
463        }
464    
465        public InputStream getURLConnectionInputStream(URLConnection conn)
466            throws IOException
467        {
468            if (System.getSecurityManager() != null)
469            {
470                try
471                {
472                    Actions actions = (Actions) m_actions.get();
473                    actions.set(Actions.GET_URL_INPUT_ACTION, conn);
474                    return (InputStream) AccessController.doPrivileged(actions, m_acc);
475                }
476                catch (PrivilegedActionException ex)
477                {
478                    if (ex.getException() instanceof IOException)
479                    {
480                        throw (IOException) ex.getException();
481                    }
482                    throw (RuntimeException) ex.getException();
483                }
484            }
485            else
486            {
487                return conn.getInputStream();
488            }
489        }
490    
491        public boolean deleteFile(File target)
492        {
493            if (System.getSecurityManager() != null)
494            {
495                try
496                {
497                    Actions actions = (Actions) m_actions.get();
498                    actions.set(Actions.DELETE_FILE_ACTION, target);
499                    return ((Boolean) AccessController.doPrivileged(actions, m_acc))
500                        .booleanValue();
501                }
502                catch (PrivilegedActionException ex)
503                {
504                    throw (RuntimeException) ex.getException();
505                }
506            }
507            else
508            {
509                return target.delete();
510            }
511        }
512    
513        public File createTempFile(String prefix, String suffix, File dir)
514            throws IOException
515        {
516            if (System.getSecurityManager() != null)
517            {
518                try
519                {
520                    Actions actions = (Actions) m_actions.get();
521                    actions.set(Actions.CREATE_TMPFILE_ACTION, prefix, suffix, dir);
522                    return (File) AccessController.doPrivileged(actions, m_acc);
523                }
524                catch (PrivilegedActionException ex)
525                {
526                    if (ex.getException() instanceof IOException)
527                    {
528                        throw (IOException) ex.getException();
529                    }
530                    throw (RuntimeException) ex.getException();
531                }
532            }
533            else
534            {
535                return File.createTempFile(prefix, suffix, dir);
536            }
537        }
538    
539        public URLConnection openURLConnection(URL url) throws IOException
540        {
541            if (System.getSecurityManager() != null)
542            {
543                try
544                {
545                    Actions actions = (Actions) m_actions.get();
546                    actions.set(Actions.OPEN_URLCONNECTION_ACTION, url);
547                    return (URLConnection) AccessController.doPrivileged(actions,
548                        m_acc);
549                }
550                catch (PrivilegedActionException ex)
551                {
552                    if (ex.getException() instanceof IOException)
553                    {
554                        throw (IOException) ex.getException();
555                    }
556                    throw (RuntimeException) ex.getException();
557                }
558            }
559            else
560            {
561                return url.openConnection();
562            }
563        }
564    
565        public JarFileX openJAR(File file) throws IOException
566        {
567            if (System.getSecurityManager() != null)
568            {
569                try
570                {
571                    Actions actions = (Actions) m_actions.get();
572                    actions.set(Actions.OPEN_JARX_ACTION, file);
573                    return (JarFileX) AccessController.doPrivileged(actions, m_acc);
574                }
575                catch (PrivilegedActionException ex)
576                {
577                    if (ex.getException() instanceof IOException)
578                    {
579                        throw (IOException) ex.getException();
580                    }
581                    throw (RuntimeException) ex.getException();
582                }
583            }
584            else
585            {
586                return new JarFileX(file);
587            }
588        }
589    
590        public JarFileX openJAR(File file, boolean verify) throws IOException
591        {
592            if (System.getSecurityManager() != null)
593            {
594                try
595                {
596                    Actions actions = (Actions) m_actions.get();
597                    actions.set(Actions.OPEN_JARX_VERIFY_ACTION, file, (verify ? Boolean.TRUE : Boolean.FALSE));
598                    return (JarFileX) AccessController.doPrivileged(actions, m_acc);
599                }
600                catch (PrivilegedActionException ex)
601                {
602                    if (ex.getException() instanceof IOException)
603                    {
604                        throw (IOException) ex.getException();
605                    }
606                    throw (RuntimeException) ex.getException();
607                }
608            }
609            else
610            {
611                return new JarFileX(file, verify);
612            }
613        }
614    // TODO: REFACTOR - SecureAction fix needed.
615    /*
616        public ModuleClassLoader createModuleClassLoader(ModuleImpl impl)
617        {
618            return createModuleClassLoader(impl, null);
619        }
620    
621        public ModuleClassLoader createModuleClassLoader(ModuleImpl impl,
622            ProtectionDomain protectionDomain)
623        {
624            if (System.getSecurityManager() != null)
625            {
626                try
627                {
628                    Actions actions = (Actions) m_actions.get();
629                    actions.set(Actions.CREATE_MODULECLASSLOADER_ACTION, impl, protectionDomain);
630                    return (ModuleClassLoader) AccessController.doPrivileged(actions, m_acc);
631                }
632                catch (PrivilegedActionException ex)
633                {
634                    throw (RuntimeException) ex.getException();
635                }
636            }
637            else
638            {
639                return new ModuleClassLoader(impl, protectionDomain);
640            }
641        }
642    */
643        public void startActivator(BundleActivator activator, BundleContext context)
644            throws Exception
645        {
646            if (System.getSecurityManager() != null)
647            {
648                try
649                {
650                    Actions actions = (Actions) m_actions.get();
651                    actions.set(Actions.START_ACTIVATOR_ACTION, activator, context);
652                    AccessController.doPrivileged(actions, m_acc);
653                }
654                catch (PrivilegedActionException ex)
655                {
656                    throw ex.getException();
657                }
658            }
659            else
660            {
661                activator.start(context);
662            }
663        }
664    
665        public void stopActivator(BundleActivator activator, BundleContext context)
666            throws Exception
667        {
668            if (System.getSecurityManager() != null)
669            {
670                try
671                {
672                    Actions actions = (Actions) m_actions.get();
673                    actions.set(Actions.STOP_ACTIVATOR_ACTION, activator, context);
674                    AccessController.doPrivileged(actions, m_acc);
675                }
676                catch (PrivilegedActionException ex)
677                {
678                    throw ex.getException();
679                }
680            }
681            else
682            {
683                activator.stop(context);
684            }
685        }
686    
687        public Policy getPolicy()
688        {
689            if (System.getSecurityManager() != null)
690            {
691                try
692                {
693                    Actions actions = (Actions) m_actions.get();
694                    actions.set(Actions.GET_POLICY_ACTION, null);
695                    return (Policy) AccessController.doPrivileged(actions, m_acc);
696                }
697                catch (PrivilegedActionException ex)
698                {
699                    throw (RuntimeException) ex.getException();
700                }
701            }
702            else
703            {
704                return Policy.getPolicy();
705            }
706        }
707    
708        public void addURLToURLClassLoader(URL extension, ClassLoader loader) throws Exception
709        {
710            if (System.getSecurityManager() != null)
711            {
712                Actions actions = (Actions) m_actions.get();
713                actions.set(Actions.ADD_EXTENSION_URL, extension, loader);
714                try
715                {
716                    AccessController.doPrivileged(actions, m_acc);
717                }
718                catch (PrivilegedActionException e)
719                {
720                    throw e.getException();
721                }
722            }
723            else
724            {
725                Method addURL =
726                    URLClassLoader.class.getDeclaredMethod("addURL",
727                    new Class[] {URL.class});
728                addURL.setAccessible(true);
729                addURL.invoke(loader, new Object[]{extension});
730            }
731        }
732    
733        public Constructor getConstructor(Class target, Class[] types) throws Exception
734        {
735            if (System.getSecurityManager() != null)
736            {
737                Actions actions = (Actions) m_actions.get();
738                actions.set(Actions.GET_CONSTRUCTOR_ACTION, target, types);
739                try
740                {
741                    return (Constructor) AccessController.doPrivileged(actions, m_acc);
742                }
743                catch (PrivilegedActionException e)
744                {
745                    throw e.getException();
746                }
747            }
748            else
749            {
750                return target.getConstructor(types);
751            }
752        }
753    
754        public Constructor getDeclaredConstructor(Class target, Class[] types) throws Exception
755        {
756            if (System.getSecurityManager() != null)
757            {
758                Actions actions = (Actions) m_actions.get();
759                actions.set(Actions.GET_DECLARED_CONSTRUCTOR_ACTION, target, types);
760                try
761                {
762                    return (Constructor) AccessController.doPrivileged(actions, m_acc);
763                }
764                catch (PrivilegedActionException e)
765                {
766                    throw e.getException();
767                }
768            }
769            else
770            {
771                return target.getDeclaredConstructor(types);
772            }
773        }
774    
775        public Method getMethod(Class target, String method, Class[] types) throws Exception
776        {
777            if (System.getSecurityManager() != null)
778            {
779                Actions actions = (Actions) m_actions.get();
780                actions.set(Actions.GET_METHOD_ACTION, target, method, types);
781                try
782                {
783                    return (Method) AccessController.doPrivileged(actions, m_acc);
784                }
785                catch (PrivilegedActionException e)
786                {
787                    throw e.getException();
788                }
789            }
790            else
791            {
792                return target.getMethod(method, types);
793            }
794        }
795    
796        public Method getDeclaredMethod(Class target, String method, Class[] types) throws Exception
797        {
798            if (System.getSecurityManager() != null)
799            {
800                Actions actions = (Actions) m_actions.get();
801                actions.set(Actions.GET_DECLARED_METHOD_ACTION, target, method, types);
802                try
803                {
804                    return (Method) AccessController.doPrivileged(actions, m_acc);
805                }
806                catch (PrivilegedActionException e)
807                {
808                    throw e.getException();
809                }
810            }
811            else
812            {
813                return target.getDeclaredMethod(method, types);
814            }
815        }
816    
817        public void setAccesssible(AccessibleObject ao)
818        {
819            if (System.getSecurityManager() != null)
820            {
821                Actions actions = (Actions) m_actions.get();
822                actions.set(Actions.SET_ACCESSIBLE_ACTION, ao);
823                try
824                {
825                    AccessController.doPrivileged(actions, m_acc);
826                }
827                catch (PrivilegedActionException e)
828                {
829                    throw (RuntimeException) e.getException();
830                }
831            }
832            else
833            {
834                ao.setAccessible(true);
835            }
836        }
837    
838        public Object invoke(Method method, Object target, Object[] params) throws Exception
839        {
840            if (System.getSecurityManager() != null)
841            {
842                Actions actions = (Actions) m_actions.get();
843                actions.set(Actions.INVOKE_METHOD_ACTION, method, target, params);
844                try
845                {
846                    return AccessController.doPrivileged(actions, m_acc);
847                }
848                catch (PrivilegedActionException e)
849                {
850                    throw e.getException();
851                }
852            }
853            else
854            {
855                method.setAccessible(true);
856                return method.invoke(target, params);
857            }
858        }
859    
860        public Object invokeDirect(Method method, Object target, Object[] params) throws Exception
861        {
862            if (System.getSecurityManager() != null)
863            {
864                Actions actions = (Actions) m_actions.get();
865                actions.set(Actions.INVOKE_DIRECTMETHOD_ACTION, method, target, params);
866                try
867                {
868                    return AccessController.doPrivileged(actions, m_acc);
869                }
870                catch (PrivilegedActionException e)
871                {
872                    throw e.getException();
873                }
874            }
875            else
876            {
877                return method.invoke(target, params);
878            }
879        }
880    
881        public Object invoke(Constructor constructor, Object[] params) throws Exception
882        {
883            if (System.getSecurityManager() != null)
884            {
885                Actions actions = (Actions) m_actions.get();
886                actions.set(Actions.INVOKE_CONSTRUCTOR_ACTION, constructor, params);
887                try
888                {
889                    return AccessController.doPrivileged(actions, m_acc);
890                }
891                catch (PrivilegedActionException e)
892                {
893                    throw e.getException();
894                }
895            }
896            else
897            {
898                return constructor.newInstance(params);
899            }
900        }
901    
902        public Object getDeclaredField(Class targetClass, String name, Object target)
903            throws Exception
904        {
905            if (System.getSecurityManager() != null)
906            {
907                Actions actions = (Actions) m_actions.get();
908                actions.set(Actions.GET_FIELD_ACTION, targetClass, name, target);
909                try
910                {
911                    return AccessController.doPrivileged(actions, m_acc);
912                }
913                catch (PrivilegedActionException e)
914                {
915                    throw e.getException();
916                }
917            }
918            else
919            {
920                Field field = targetClass.getDeclaredField(name);
921                field.setAccessible(true);
922    
923                return field.get(target);
924            }
925        }
926    
927        public Object swapStaticFieldIfNotClass(Class targetClazz,
928            Class targetType, Class condition, String lockName) throws Exception
929        {
930            if (System.getSecurityManager() != null)
931            {
932                Actions actions = (Actions) m_actions.get();
933                actions.set(Actions.SWAP_FIELD_ACTION, targetClazz, targetType,
934                    condition, lockName);
935                try
936                {
937                    return AccessController.doPrivileged(actions, m_acc);
938                }
939                catch (PrivilegedActionException e)
940                {
941                    throw e.getException();
942                }
943            }
944            else
945            {
946                return _swapStaticFieldIfNotClass(targetClazz, targetType,
947                    condition, lockName);
948            }
949        }
950    
951        private static Object _swapStaticFieldIfNotClass(Class targetClazz,
952            Class targetType, Class condition, String lockName) throws Exception
953        {
954            Object lock = null;
955            if (lockName != null)
956            {
957                try
958                {
959                    Field lockField =
960                        targetClazz.getDeclaredField(lockName);
961                    lockField.setAccessible(true);
962                    lock = lockField.get(null);
963                }
964                catch (NoSuchFieldException ex)
965                {
966                }
967            }
968            if (lock == null)
969            {
970                lock = targetClazz;
971            }
972            synchronized (lock)
973            {
974                Field[] fields = targetClazz.getDeclaredFields();
975    
976                Object result = null;
977                for (int i = 0; (i < fields.length) && (result == null); i++)
978                {
979                    if (Modifier.isStatic(fields[i].getModifiers()) &&
980                        (fields[i].getType() == targetType))
981                    {
982                        fields[i].setAccessible(true);
983    
984                        result = fields[i].get(null);
985    
986                        if (result != null)
987                        {
988                            if ((condition == null) ||
989                                !result.getClass().getName().equals(condition.getName()))
990                            {
991                                fields[i].set(null, null);
992                            }
993                        }
994                    }
995                }
996                if (result != null)
997                {
998                    if ((condition == null) || !result.getClass().getName().equals(condition.getName()))
999                    {
1000                        // reset cache
1001                        for (int i = 0; i < fields.length; i++)
1002                        {
1003                            if (Modifier.isStatic(fields[i].getModifiers()) &&
1004                                (fields[i].getType() == Hashtable.class))
1005                            {
1006                                fields[i].setAccessible(true);
1007                                Hashtable cache = (Hashtable) fields[i].get(null);
1008                                if (cache != null)
1009                                {
1010                                    cache.clear();
1011                                }
1012                            }
1013                        }
1014                    }
1015                    return result;
1016                }
1017            }
1018            return null;
1019        }
1020    
1021        public void flush(Class targetClazz, Object lock) throws Exception
1022        {
1023            if (System.getSecurityManager() != null)
1024            {
1025                Actions actions = (Actions) m_actions.get();
1026                actions.set(Actions.FLUSH_FIELD_ACTION, targetClazz, lock);
1027                try
1028                {
1029                    AccessController.doPrivileged(actions, m_acc);
1030                }
1031                catch (PrivilegedActionException e)
1032                {
1033                    throw e.getException();
1034                }
1035            }
1036            else
1037            {
1038                _flush(targetClazz, lock);
1039            }
1040        }
1041    
1042        private static void _flush(Class targetClazz, Object lock) throws Exception
1043        {
1044            synchronized (lock) 
1045            {
1046                Field[] fields = targetClazz.getDeclaredFields();
1047                // reset cache
1048                for (int i = 0; i < fields.length; i++)
1049                {
1050                    if (Modifier.isStatic(fields[i].getModifiers()) &&
1051                        ((fields[i].getType() == Hashtable.class) || (fields[i].getType() == HashMap.class)))
1052                    {
1053                        fields[i].setAccessible(true);
1054                        if (fields[i].getType() == Hashtable.class)
1055                        {
1056                            Hashtable cache = (Hashtable) fields[i].get(null);
1057                            if (cache != null)
1058                            {
1059                                cache.clear();
1060                            }
1061                        }
1062                        else
1063                        {
1064                            HashMap cache = (HashMap) fields[i].get(null);
1065                            if (cache != null)
1066                            {
1067                                cache.clear();
1068                            }
1069                        }
1070                    }
1071                }
1072            }
1073        }
1074    
1075        private static class Actions implements PrivilegedExceptionAction
1076        {
1077            public static final int INITIALIZE_CONTEXT = 0;
1078    
1079            public static final int ADD_EXTENSION_URL = 1;
1080            public static final int CREATE_MODULECLASSLOADER_ACTION = 2;
1081            public static final int CREATE_TMPFILE_ACTION = 3;
1082            public static final int CREATE_URL_ACTION = 4;
1083            public static final int CREATE_URL_WITH_CONTEXT_ACTION = 5;
1084            public static final int DELETE_FILE_ACTION = 6;
1085            public static final int EXEC_ACTION = 7;
1086            public static final int FILE_EXISTS_ACTION = 8;
1087            public static final int FILE_IS_DIRECTORY_ACTION = 9;
1088            public static final int FOR_NAME_ACTION = 10;
1089            public static final int GET_ABSOLUTE_PATH_ACTION = 11;
1090            public static final int GET_CONSTRUCTOR_ACTION = 12;
1091            public static final int GET_DECLARED_CONSTRUCTOR_ACTION = 13;
1092            public static final int GET_DECLARED_METHOD_ACTION = 14;
1093            public static final int GET_FIELD_ACTION = 15;
1094            public static final int GET_FILE_INPUT_ACTION = 16;
1095            public static final int GET_FILE_OUTPUT_ACTION = 17;
1096            public static final int GET_METHOD_ACTION = 19;
1097            public static final int GET_POLICY_ACTION = 20;
1098            public static final int GET_PROPERTY_ACTION = 21;
1099            public static final int GET_PARENT_CLASS_LOADER_ACTION = 22;
1100            public static final int GET_SYSTEM_CLASS_LOADER_ACTION = 23;
1101            public static final int GET_URL_INPUT_ACTION = 24;
1102            public static final int INVOKE_CONSTRUCTOR_ACTION = 25;
1103            public static final int INVOKE_DIRECTMETHOD_ACTION = 26;
1104            public static final int INVOKE_METHOD_ACTION = 27;
1105            public static final int LIST_DIRECTORY_ACTION = 28;
1106            public static final int MAKE_DIRECTORIES_ACTION = 29;
1107            public static final int MAKE_DIRECTORY_ACTION = 30;
1108            public static final int OPEN_JARX_ACTION = 31;
1109            public static final int OPEN_JARX_VERIFY_ACTION = 32;
1110            public static final int OPEN_URLCONNECTION_ACTION = 33;
1111            public static final int RENAME_FILE_ACTION = 34;
1112            public static final int SET_ACCESSIBLE_ACTION = 35;
1113            public static final int START_ACTIVATOR_ACTION = 36;
1114            public static final int STOP_ACTIVATOR_ACTION = 37;
1115            public static final int SWAP_FIELD_ACTION = 38;
1116            public static final int SYSTEM_EXIT_ACTION = 39;
1117            public static final int FLUSH_FIELD_ACTION = 40;
1118            public static final int GET_CLASS_LOADER_ACTION = 41;
1119    
1120            private int m_action = -1;
1121            private Object m_arg1 = null;
1122            private Object m_arg2 = null;
1123            private Object m_arg3 = null;
1124            private Object m_arg4 = null;
1125            private Object m_arg5 = null;
1126    
1127            public void set(int action)
1128            {
1129                m_action = action;
1130            }
1131    
1132            public void set(int action, Object arg1)
1133            {
1134                m_action = action;
1135                m_arg1 = arg1;
1136            }
1137    
1138            public void set(int action, Object arg1, Object arg2)
1139            {
1140                m_action = action;
1141                m_arg1 = arg1;
1142                m_arg2 = arg2;
1143            }
1144    
1145            public void set(int action, Object arg1, Object arg2, Object arg3)
1146            {
1147                m_action = action;
1148                m_arg1 = arg1;
1149                m_arg2 = arg2;
1150                m_arg3 = arg3;
1151            }
1152    
1153            public void set(int action, Object arg1, Object arg2, Object arg3,
1154                Object arg4)
1155            {
1156                m_action = action;
1157                m_arg1 = arg1;
1158                m_arg2 = arg2;
1159                m_arg3 = arg3;
1160                m_arg4 = arg4;
1161            }
1162    
1163            public void set(int action, Object arg1, Object arg2, Object arg3,
1164                Object arg4, Object arg5)
1165            {
1166                m_action = action;
1167                m_arg1 = arg1;
1168                m_arg2 = arg2;
1169                m_arg3 = arg3;
1170                m_arg4 = arg4;
1171                m_arg5 = arg5;
1172            }
1173    
1174            private void unset()
1175            {
1176                m_action = -1;
1177                m_arg1 = null;
1178                m_arg2 = null;
1179                m_arg3 = null;
1180                m_arg4 = null;
1181                m_arg5 = null;
1182            }
1183    
1184            public Object run() throws Exception
1185            {
1186                int action =  m_action;
1187                Object arg1 = m_arg1;
1188                Object arg2 = m_arg2;
1189                Object arg3 = m_arg3;
1190                Object arg4 = m_arg4;
1191                Object arg5 = m_arg5;
1192    
1193                unset();
1194    
1195                if (action == INITIALIZE_CONTEXT)
1196                {
1197                    return AccessController.getContext();
1198                }
1199                else if (action == GET_PROPERTY_ACTION)
1200                {
1201                    return System.getProperty((String) arg1, (String) arg2);
1202                }
1203                else if (action == GET_PARENT_CLASS_LOADER_ACTION)
1204                {
1205                    return ((ClassLoader) arg1).getParent();
1206                }
1207                else if (action == GET_SYSTEM_CLASS_LOADER_ACTION)
1208                {
1209                    return ClassLoader.getSystemClassLoader();
1210                }
1211                else if (action == FOR_NAME_ACTION)
1212                {
1213                    return Class.forName((String) arg1);
1214                }
1215                else if (action == CREATE_URL_ACTION)
1216                {
1217                    return new URL((String) arg1, (String) arg2,
1218                        ((Integer) arg3).intValue(), (String) arg4,
1219                        (URLStreamHandler) arg5);
1220                }
1221                else if (action == CREATE_URL_WITH_CONTEXT_ACTION)
1222                {
1223                    return new URL((URL) arg1, (String) arg2,
1224                        (URLStreamHandler) arg3);
1225                }
1226                else if (action == EXEC_ACTION)
1227                {
1228                    return Runtime.getRuntime().exec((String) arg1);
1229                }
1230                else if (action == GET_ABSOLUTE_PATH_ACTION)
1231                {
1232                    return ((File) arg1).getAbsolutePath();
1233                }
1234                else if (action == FILE_EXISTS_ACTION)
1235                {
1236                    return ((File) arg1).exists() ? Boolean.TRUE : Boolean.FALSE;
1237                }
1238                else if (action == FILE_IS_DIRECTORY_ACTION)
1239                {
1240                    return ((File) arg1).isDirectory() ? Boolean.TRUE : Boolean.FALSE;
1241                }
1242                else if (action == MAKE_DIRECTORY_ACTION)
1243                {
1244                    return ((File) arg1).mkdir() ? Boolean.TRUE : Boolean.FALSE;
1245                }
1246                else if (action == MAKE_DIRECTORIES_ACTION)
1247                {
1248                    return ((File) arg1).mkdirs() ? Boolean.TRUE : Boolean.FALSE;
1249                }
1250                else if (action == LIST_DIRECTORY_ACTION)
1251                {
1252                    return ((File) arg1).listFiles();
1253                }
1254                else if (action == RENAME_FILE_ACTION)
1255                {
1256                    return ((File) arg1).renameTo((File) arg2) ? Boolean.TRUE : Boolean.FALSE;
1257                }
1258                else if (action == GET_FILE_INPUT_ACTION)
1259                {
1260                    return new FileInputStream((File) arg1);
1261                }
1262                else if (action == GET_FILE_OUTPUT_ACTION)
1263                {
1264                    return new FileOutputStream((File) arg1);
1265                }
1266                else if (action == DELETE_FILE_ACTION)
1267                {
1268                    return ((File) arg1).delete() ? Boolean.TRUE : Boolean.FALSE;
1269                }
1270                else if (action == OPEN_JARX_ACTION)
1271                {
1272                    return new JarFileX((File) arg1);
1273                }
1274                else if (action == OPEN_JARX_VERIFY_ACTION)
1275                {
1276                    return new JarFileX((File) arg1, ((Boolean) arg2).booleanValue());
1277                }
1278                else if (action == GET_URL_INPUT_ACTION)
1279                {
1280                    return ((URLConnection) arg1).getInputStream();
1281                }
1282                else if (action == START_ACTIVATOR_ACTION)
1283                {
1284                    ((BundleActivator) arg1).start((BundleContext) arg2);
1285                    return null;
1286                }
1287                else if (action == STOP_ACTIVATOR_ACTION)
1288                {
1289                    ((BundleActivator) arg1).stop((BundleContext) arg2);
1290                    return null;
1291                }
1292                else if (action == SYSTEM_EXIT_ACTION)
1293                {
1294                    System.exit(((Integer) arg1).intValue());
1295                }
1296                else if (action == GET_POLICY_ACTION)
1297                {
1298                    return Policy.getPolicy();
1299                }
1300                else if (action == CREATE_TMPFILE_ACTION)
1301                {
1302                    return File.createTempFile((String) arg1, (String) arg2,
1303                        (File) arg3);
1304                }
1305                else if (action == OPEN_URLCONNECTION_ACTION)
1306                {
1307                    return ((URL) arg1).openConnection();
1308                }
1309                else if (action == ADD_EXTENSION_URL)
1310                {
1311                    Method addURL =
1312                        URLClassLoader.class.getDeclaredMethod("addURL",
1313                        new Class[] {URL.class});
1314                    addURL.setAccessible(true);
1315                    addURL.invoke(arg2, new Object[]{arg1});
1316                }
1317                else if (action == GET_CONSTRUCTOR_ACTION)
1318                {
1319                    return ((Class) arg1).getConstructor((Class[]) arg2);
1320                }
1321                else if (action == GET_DECLARED_CONSTRUCTOR_ACTION)
1322                {
1323                    return ((Class) arg1).getDeclaredConstructor((Class[]) arg2);
1324                }
1325                else if (action == GET_METHOD_ACTION)
1326                {
1327                    return ((Class) arg1).getMethod((String) arg2, (Class[]) arg3);
1328                }
1329                else if (action == INVOKE_METHOD_ACTION)
1330                {
1331                    ((Method) arg1).setAccessible(true);
1332                    return ((Method) arg1).invoke(arg2, (Object[]) arg3);
1333                }
1334                else if (action == INVOKE_DIRECTMETHOD_ACTION)
1335                {
1336                    return ((Method) arg1).invoke(arg2, (Object[]) arg3);
1337                }
1338                else if (action == INVOKE_CONSTRUCTOR_ACTION)
1339                {
1340                    return ((Constructor) arg1).newInstance((Object[]) arg2);
1341                }
1342                else if (action == SWAP_FIELD_ACTION)
1343                {
1344                    return _swapStaticFieldIfNotClass((Class) arg1,
1345                        (Class) arg2, (Class) arg3, (String) arg4);
1346                }
1347                else if (action == GET_FIELD_ACTION)
1348                {
1349                    Field field = ((Class) arg1).getDeclaredField((String) arg2);
1350                    field.setAccessible(true);
1351                    return field.get(arg3);
1352                }
1353                else if (action == GET_DECLARED_METHOD_ACTION)
1354                {
1355                    return ((Class) arg1).getDeclaredMethod((String) arg2, (Class[]) arg3);
1356                }
1357                else if (action == SET_ACCESSIBLE_ACTION)
1358                {
1359                    ((AccessibleObject) arg1).setAccessible(true);
1360                }
1361                else if (action == FLUSH_FIELD_ACTION)
1362                {
1363                    _flush(((Class) arg1), arg2);
1364                }
1365                else if (action == GET_CLASS_LOADER_ACTION)
1366                {
1367                    return ((Class) arg1).getClassLoader();
1368                }
1369    
1370                return null;
1371            }
1372        }
1373    }