Source Code Cross Referenced for MX4JRemoteUtils.java in  » JMX » mx4j » mx4j » remote » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » JMX » mx4j » mx4j.remote 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright (C) The MX4J Contributors.
003:         * All rights reserved.
004:         *
005:         * This software is distributed under the terms of the MX4J License version 1.0.
006:         * See the terms of the MX4J License in the documentation provided with this software.
007:         */
008:
009:        package mx4j.remote;
010:
011:        import java.io.ByteArrayOutputStream;
012:        import java.io.IOException;
013:        import java.io.ObjectOutputStream;
014:        import java.io.Serializable;
015:        import java.lang.reflect.Constructor;
016:        import java.net.URL;
017:        import java.security.AccessControlContext;
018:        import java.security.AccessControlException;
019:        import java.security.AccessController;
020:        import java.security.CodeSource;
021:        import java.security.DomainCombiner;
022:        import java.security.Permission;
023:        import java.security.PermissionCollection;
024:        import java.security.Principal;
025:        import java.security.PrivilegedAction;
026:        import java.security.PrivilegedActionException;
027:        import java.security.PrivilegedExceptionAction;
028:        import java.security.ProtectionDomain;
029:        import java.security.cert.Certificate;
030:        import java.util.HashMap;
031:        import java.util.Iterator;
032:        import java.util.Map;
033:        import java.util.Set;
034:        import javax.management.remote.SubjectDelegationPermission;
035:        import javax.security.auth.AuthPermission;
036:        import javax.security.auth.Policy;
037:        import javax.security.auth.Subject;
038:
039:        import mx4j.log.Log;
040:        import mx4j.log.Logger;
041:
042:        /**
043:         * @version $Revision: 1.19 $
044:         */
045:        public class MX4JRemoteUtils {
046:            private static int connectionNumber;
047:
048:            /**
049:             * Returns a copy of the given Map that does not contain non-serializable entries
050:             */
051:            public static Map removeNonSerializableEntries(Map map) {
052:                Map newMap = new HashMap(map.size());
053:                for (Iterator i = map.entrySet().iterator(); i.hasNext();) {
054:                    Map.Entry entry = (Map.Entry) i.next();
055:                    if (isSerializable(entry))
056:                        newMap.put(entry.getKey(), entry.getValue());
057:                }
058:                return newMap;
059:            }
060:
061:            private static boolean isSerializable(Object object) {
062:                if (object instanceof  Map.Entry)
063:                    return isSerializable(((Map.Entry) object).getKey())
064:                            && isSerializable(((Map.Entry) object).getValue());
065:                if (object == null)
066:                    return true;
067:                if (object instanceof  String)
068:                    return true;
069:                if (object instanceof  Number)
070:                    return true;
071:                if (!(object instanceof  Serializable))
072:                    return false;
073:
074:                return isTrulySerializable(object);
075:            }
076:
077:            public static boolean isTrulySerializable(Object object) {
078:                // Give up and serialize the object
079:                try {
080:                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
081:                    ObjectOutputStream oos = new ObjectOutputStream(baos);
082:                    oos.writeObject(object);
083:                    oos.close();
084:                    return true;
085:                } catch (IOException ignored) {
086:                }
087:                return false;
088:            }
089:
090:            public static String createConnectionID(String protocol,
091:                    String callerAddress, int callerPort, Subject subject) {
092:                // See JSR 160 specification at javax/management/remote/package-summary.html
093:
094:                StringBuffer buffer = new StringBuffer(protocol);
095:                buffer.append(':');
096:                if (callerAddress != null)
097:                    buffer.append("//").append(callerAddress);
098:                if (callerPort >= 0)
099:                    buffer.append(':').append(callerPort);
100:                buffer.append(' ');
101:
102:                if (subject != null) {
103:                    Set principals = subject.getPrincipals();
104:                    for (Iterator i = principals.iterator(); i.hasNext();) {
105:                        Principal principal = (Principal) i.next();
106:                        String name = principal.getName();
107:                        name = name.replace(' ', '_');
108:                        buffer.append(name);
109:                        if (i.hasNext())
110:                            buffer.append(';');
111:                    }
112:                }
113:                buffer.append(' ');
114:
115:                buffer.append("0x").append(
116:                        Integer.toHexString(getNextConnectionNumber())
117:                                .toUpperCase());
118:
119:                return buffer.toString();
120:            }
121:
122:            private static synchronized int getNextConnectionNumber() {
123:                return ++connectionNumber;
124:            }
125:
126:            private static Logger getLogger() {
127:                return Log.getLogger(MX4JRemoteUtils.class.getName());
128:            }
129:
130:            public static Object subjectInvoke(Subject subject,
131:                    Subject delegate, AccessControlContext context,
132:                    Map environment, PrivilegedExceptionAction action)
133:                    throws Exception {
134:                if (delegate != null) {
135:                    if (subject == null)
136:                        throw new SecurityException(
137:                                "There is no authenticated subject to delegate to");
138:                    checkSubjectDelegationPermission(delegate,
139:                            getSubjectContext(subject, null, context,
140:                                    environment));
141:                }
142:
143:                Logger logger = getLogger();
144:
145:                // If there is no authenticated subject, I leave the transport library to perform its job.
146:                // In the RMIConnectorServer, the context at start() time is used by the RMI runtime to
147:                // restrict permissions via a doPrivileged() call.
148:                // In HTTP JMXConnectorServer, it's the HTTP server responsibility to give such semantic,
149:                // if it wants to.
150:                // Here, I just execute the action and trust the transport library to do its job right.
151:                if (subject == null) {
152:                    if (logger.isEnabledFor(Logger.TRACE))
153:                        logger
154:                                .trace("No authenticated subject, invoking action without using Subject.doAs");
155:                    return action.run();
156:                }
157:
158:                // The precedent stack frames have normally AllPermission, since - for example in RMI - they
159:                // are JDK domains or JMX/MX4J domains. Below I take the context, and I
160:                // inject the JSR 160 domain with the authenticated Subject, then call Subject.doAsPrivileged()
161:                // with, eventually, the delegate Subject.
162:                // Must call Subject.doAs, since anyone down in the stack call can call Subject.getSubject()
163:                // and expect to get the Subject or the delegate, even in absence of the SecurityManager
164:                try {
165:                    if (delegate == null) {
166:                        if (logger.isEnabledFor(Logger.TRACE))
167:                            logger
168:                                    .trace("Invoking Subject.doAs using authenticated subject "
169:                                            + subject);
170:                        return Subject.doAsPrivileged(subject, action,
171:                                getSubjectContext(subject, delegate, context,
172:                                        environment));
173:                    } else {
174:                        if (logger.isEnabledFor(Logger.TRACE))
175:                            logger
176:                                    .trace("Invoking Subject.doAs using delegate subject "
177:                                            + delegate);
178:                        return Subject.doAsPrivileged(delegate, action,
179:                                getSubjectContext(subject, delegate, context,
180:                                        environment));
181:                    }
182:                } catch (PrivilegedActionException x) {
183:                    throw x.getException();
184:                }
185:            }
186:
187:            private static void checkSubjectDelegationPermission(
188:                    final Subject delegate, AccessControlContext context)
189:                    throws SecurityException {
190:                Logger logger = getLogger();
191:
192:                SecurityManager sm = System.getSecurityManager();
193:                if (sm == null) {
194:                    if (logger.isEnabledFor(Logger.TRACE))
195:                        logger
196:                                .trace("No SecurityManager, skipping Subject delegation permission check");
197:                    return;
198:                }
199:
200:                AccessController.doPrivileged(new PrivilegedAction() {
201:                    public Object run() {
202:                        StringBuffer buffer = new StringBuffer();
203:                        Set principals = delegate.getPrincipals();
204:                        for (Iterator i = principals.iterator(); i.hasNext();) {
205:                            Principal principal = (Principal) i.next();
206:                            buffer.setLength(0);
207:                            String permission = buffer.append(
208:                                    principal.getClass().getName()).append(".")
209:                                    .append(principal.getName()).toString();
210:                            AccessController
211:                                    .checkPermission(new SubjectDelegationPermission(
212:                                            permission));
213:                        }
214:                        return null;
215:                    }
216:                }, context);
217:            }
218:
219:            /**
220:             * Returns a suitable AccessControlContext that restricts access in a {@link Subject#doAsPrivileged} call
221:             * based on the current JAAS authorization policy, and combined with the given context.
222:             * <br/>
223:             * This is needed because the server stack frames in a call to a JMXConnectorServer are,
224:             * for example for RMI, like this:
225:             * <pre>
226:             * java.lang.Thread.run()
227:             *   [rmi runtime classes]
228:             *     javax.management.remote.rmi.RMIConnectionImpl
229:             *       [mx4j JSR 160 implementation code]
230:             *         javax.security.auth.Subject.doAsPrivileged()
231:             *           [mx4j JSR 160 implementation code]
232:             *             [mx4j JSR 3 implementation code]
233:             *               java.lang.SecurityManager.checkPermission()
234:             * </pre>
235:             * All protection domains in this stack frames have AllPermission, normally, so that when the JMX implementation
236:             * checks for permissions, it will always pass the check.
237:             * <br/>
238:             * One solution would be to use a doPrivileged() call with a restricting context (normally created at the start()
239:             * of the connector server), but this forces to grant to the code that starts the connector server all the
240:             * permissions needed by clients, and furthermore, grants to clients the permissions needed to start the connector
241:             * server.
242:             * <br/>
243:             * Therefore, a "special" ProtectionDomain will be injected in the AccessControlContext returned by this method.
244:             * This special ProtectionDomain will have a CodeSource with null location and the principals specified by the
245:             * subject passed as argument.
246:             * <br/>
247:             * The "injection" of this synthetic ProtectionDomain allows to give AllPermission to the JSR 3 and 160 classes
248:             * and implementation, but still have the possibility to specify a JAAS policy with MBeanPermissions in this way:
249:             * <pre>
250:             * grant principal javax.management.remote.JMXPrincipal "mx4j"
251:             * {
252:             *    permission javax.management.MBeanPermission "*", "getAttribute";
253:             * };
254:             * </pre>
255:             * MX4J also offer an alternative implementation that checks if the given context has a
256:             * {@link SubjectDelegationPermission} for the given subject; if so, the policy configuration is much simpler
257:             * since does not require that the context has all the possible permissions needed by code down the stack.
258:             * This also allows to specify separately the permissions to start the connector server
259:             * and the permissions needed by clients.
260:             */
261:            private static AccessControlContext getSubjectContext(
262:                    final Subject subject, Subject delegate,
263:                    final AccessControlContext context, Map environment) {
264:                final Logger logger = getLogger();
265:
266:                SecurityManager sm = System.getSecurityManager();
267:                if (sm == null) {
268:                    if (logger.isEnabledFor(Logger.TRACE))
269:                        logger
270:                                .trace("No security manager, injecting JSR 160 domain only");
271:                    // Just return the injected domain, to allow Subject.getSubject() return correct values
272:                    InjectingDomainCombiner combiner = new InjectingDomainCombiner(
273:                            delegate != null ? delegate : subject);
274:                    return new AccessControlContext(
275:                            new ProtectionDomain[] { combiner
276:                                    .getInjectedProtectionDomain() });
277:                }
278:
279:                // Check if the caller can delegate to a subject
280:                boolean combine = ((Boolean) AccessController.doPrivileged(
281:                        new PrivilegedAction() {
282:                            public Object run() {
283:                                try {
284:                                    // Here use the authenticated subject, not the delegate
285:                                    checkSubjectDelegationPermission(subject,
286:                                            context);
287:                                    if (logger.isEnabledFor(Logger.TRACE))
288:                                        logger
289:                                                .trace("Check for SubjectDelegationPermission passed, avoiding security domains combination");
290:                                    return Boolean.FALSE;
291:                                } catch (AccessControlException x) {
292:                                    if (logger.isEnabledFor(Logger.TRACE))
293:                                        logger
294:                                                .trace("Check for SubjectDelegationPermission not passed, combining security domains");
295:                                    return Boolean.TRUE;
296:                                }
297:                            }
298:                        }, context)).booleanValue();
299:
300:                if (combine) {
301:                    final InjectingDomainCombiner combiner = new InjectingDomainCombiner(
302:                            delegate != null ? delegate : subject);
303:                    AccessControlContext acc = (AccessControlContext) AccessController
304:                            .doPrivileged(new PrivilegedAction() {
305:                                public Object run() {
306:                                    return new AccessControlContext(context,
307:                                            combiner);
308:                                }
309:                            });
310:                    AccessController.doPrivileged(new PrivilegedAction() {
311:                        public Object run() {
312:                            try {
313:                                // Check this permission, that is required anyway, to combine the domains
314:                                AccessController
315:                                        .checkPermission(new AuthPermission(
316:                                                "doAsPrivileged"));
317:                            } catch (AccessControlException ignored) {
318:                            }
319:                            return null;
320:                        }
321:                    }, acc);
322:                    ProtectionDomain[] combined = combiner.getCombinedDomains();
323:                    return new AccessControlContext(combined);
324:                } else {
325:                    InjectingDomainCombiner combiner = new InjectingDomainCombiner(
326:                            delegate != null ? delegate : subject);
327:                    return new AccessControlContext(
328:                            new ProtectionDomain[] { combiner
329:                                    .getInjectedProtectionDomain() });
330:                }
331:            }
332:
333:            private static class InjectingDomainCombiner implements 
334:                    DomainCombiner {
335:                private static Constructor domainConstructor;
336:
337:                static {
338:                    try {
339:                        domainConstructor = ProtectionDomain.class
340:                                .getConstructor(new Class[] { CodeSource.class,
341:                                        PermissionCollection.class,
342:                                        ClassLoader.class, Principal[].class });
343:                    } catch (Exception x) {
344:                    }
345:                }
346:
347:                private ProtectionDomain domain;
348:                private ProtectionDomain[] combined;
349:
350:                public InjectingDomainCombiner(Subject subject) {
351:                    if (domainConstructor != null) {
352:                        Principal[] principals = (Principal[]) subject
353:                                .getPrincipals().toArray(new Principal[0]);
354:                        try {
355:                            Object[] args = new Object[] {
356:                                    new CodeSource((URL) null,
357:                                            (Certificate[]) null), null, null,
358:                                    principals };
359:                            domain = (ProtectionDomain) domainConstructor
360:                                    .newInstance(args);
361:                        } catch (Exception x) {
362:                        }
363:                    }
364:
365:                    if (domain == null) {
366:                        // This is done for JDK 1.3 compatibility.
367:                        domain = new SubjectProtectionDomain(new CodeSource(
368:                                (URL) null, (Certificate[]) null), subject);
369:                    }
370:                }
371:
372:                public ProtectionDomain getInjectedProtectionDomain() {
373:                    return domain;
374:                }
375:
376:                public ProtectionDomain[] combine(ProtectionDomain[] current,
377:                        ProtectionDomain[] assigned) {
378:                    ProtectionDomain[] result = null;
379:
380:                    if (current == null || current.length == 0) {
381:                        if (assigned == null || assigned.length == 0) {
382:                            result = new ProtectionDomain[1];
383:                        } else {
384:                            result = new ProtectionDomain[assigned.length + 1];
385:                            System.arraycopy(assigned, 0, result, 1,
386:                                    assigned.length);
387:                        }
388:                    } else {
389:                        if (assigned == null || assigned.length == 0) {
390:                            result = new ProtectionDomain[current.length + 1];
391:                            System.arraycopy(current, 0, result, 1,
392:                                    current.length);
393:                        } else {
394:                            result = new ProtectionDomain[current.length
395:                                    + assigned.length + 1];
396:                            System.arraycopy(current, 0, result, 1,
397:                                    current.length);
398:                            System.arraycopy(assigned, 0, result,
399:                                    current.length + 1, assigned.length);
400:                        }
401:                    }
402:
403:                    result[0] = domain;
404:                    this .combined = result;
405:
406:                    Logger logger = getLogger();
407:                    if (logger.isEnabledFor(Logger.TRACE)) {
408:                        logger.trace("Security domains combination");
409:                        logger.trace("Current domains");
410:                        logger.trace(dumpDomains(current));
411:                        logger.trace("Assigned domains");
412:                        logger.trace(dumpDomains(assigned));
413:                        logger.trace("Combined domains");
414:                        logger.trace(dumpDomains(result));
415:                    }
416:
417:                    return result;
418:                }
419:
420:                private String dumpDomains(ProtectionDomain[] domains) {
421:                    if (domains == null)
422:                        return "null";
423:                    StringBuffer buffer = new StringBuffer();
424:                    for (int i = domains.length - 1; i >= 0; --i) {
425:                        int k = domains.length - 1 - i;
426:                        while (k-- > 0)
427:                            buffer.append("  ");
428:                        buffer.append(domains[i].getCodeSource().getLocation());
429:                        // Only work in JDK 1.4
430:                        //            buffer.append(" - ");
431:                        //            buffer.append(java.util.Arrays.asList(domains[i].getPrincipals()));
432:                        buffer.append("\n");
433:                    }
434:                    return buffer.toString();
435:                }
436:
437:                public ProtectionDomain[] getCombinedDomains() {
438:                    return combined;
439:                }
440:
441:                private static class SubjectProtectionDomain extends
442:                        ProtectionDomain {
443:                    private final Subject subject;
444:
445:                    public SubjectProtectionDomain(CodeSource codesource,
446:                            Subject subject) {
447:                        super (codesource, null);
448:                        this .subject = subject;
449:                    }
450:
451:                    public boolean implies(Permission permission) {
452:                        Policy policy = (Policy) AccessController
453:                                .doPrivileged(new PrivilegedAction() {
454:                                    public Object run() {
455:                                        return Policy.getPolicy();
456:                                    }
457:                                });
458:                        PermissionCollection permissions = policy
459:                                .getPermissions(subject, getCodeSource());
460:                        return permissions.implies(permission);
461:                    }
462:                }
463:            }
464:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.