Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / January 2008

Tip: Looking for answers? Try searching our database.

How to let the methods of a class only can be invoked by a special     package(the class not in the package)?

Thread view: 
Jebel.Star@gmail.com - 22 Jan 2008 04:01 GMT
There is a class A in package XX.ZZ.GG , and A has a static method
A.GetInstance(). There are 3 classes B, C, D in package XX.ZZ .
How can I make the A.GetInstance() only can be invoked by the B, C and
D.
Roedy Green - 22 Jan 2008 04:42 GMT
>How can I make the A.GetInstance() only can be invoked by the B, C and
>D.

There are three levels: public -- everyone, package, just in same
package, and private -- just current class.

To pull off what you want means putting the classes that can talk in
the same package.

see http://mindprod.com/jgloss/package.html
Signature

Roedy Green, Canadian Mind Products
The Java Glossary, http://mindprod.com

Lew - 22 Jan 2008 14:50 GMT
>> How can I make the A.GetInstance() only can be invoked by the B, C and
>> D.
>
> There are three levels: public -- everyone, package, just in same
> package, and private -- just current class.

And protected - package-private plus inheriting classes.  Don't forget.

Signature

Lew

Patricia Shanahan - 22 Jan 2008 04:51 GMT
> There is a class A in package XX.ZZ.GG , and A has a static method
> A.GetInstance(). There are 3 classes B, C, D in package XX.ZZ .
> How can I make the A.GetInstance() only can be invoked by the B, C and
> D.

There are really untidy things you could do at run time to get a stack
trace and check that the caller is one of the specified method.

However, it would be much better to reorganize the packaging.

Patricia
Jebel.Star@gmail.com - 22 Jan 2008 05:23 GMT
> Jebel.S...@gmail.com wrote:
> > There is a class A in package XX.ZZ.GG , and A has a static method
[quoted text clipped - 8 lines]
>
> Patricia

Unfortunately I have no right to reorganize the packaging, and I don't
known how to get a stack in the JVM with Ver 1.3 .
Lew - 22 Jan 2008 14:53 GMT
>> Jebel.S...@gmail.com wrote:
>>> There is a class A in package XX.ZZ.GG , and A has a static method
>>> A.GetInstance(). There are 3 classes B, C, D in package XX.ZZ .
>>> How can I make the A.GetInstance() only can be invoked by the B, C and
>>> D.

Can you make the A.staticMethod() protected?

If so, protected access might give you partial protection - any other package
can have an extending class, but they must do so in order to access the method.

<http://java.sun.com/docs/books/jls/third_edition/html/names.html#6.6>
<http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.2.1>

Signature

Lew

Andreas Leitgeb - 22 Jan 2008 16:03 GMT
>> Jebel.S...@gmail.com wrote:
>> > There is a class A in package XX.ZZ.GG , and A has a static method
[quoted text clipped - 10 lines]
> Unfortunately I have no right to reorganize the packaging, and I don't
> known how to get a stack in the JVM with Ver 1.3 .

You could throw an exception, catch it immediately, and see what you
can read from the exception's  printStackTrace(), by passing it your
own PrintWriter (or PrintStream), wrapped around some ByteArrayOutputStream.

I just tried it with an (admittedly newer-than-1.3) java:
class X {
 public static void main(String[] args) { foo(); }
 public static int foo() {
   try {
      throw new Exception("foo");
   } catch (Exception e) {
      e.printStackTrace(System.out);
   }
   return 0;
 }
}
Try, if that also works with java-1.3, in that it also
writes the "outer"-levels.  To implement this in to-be-
protected code, You'd of course not print to stdout, but
instead to a bytearray.
Happy parsing that automatically. :-)

... But then, again, it's quite an unusual wish, what you made.
Jebel.Star@gmail.com - 24 Jan 2008 03:52 GMT
On Jan 23, 12:03 am, Andreas Leitgeb <a...@gamma.logic.tuwien.ac.at>
wrote:
> Jebel.S...@gmail.com <Jebel.S...@gmail.com> wrote:
> >> Jebel.S...@gmail.com wrote:
[quoted text clipped - 35 lines]
>
> ... But then, again, it's quite an unusual wish, what you made.

Thanks for all of you. You let me to find the limitation of my design.
So I change it.

I changed my design:

1 Add a protect method GetInstance() in Class B;
2 Add a class E which is extends from B in package XX.ZZ.GG. Create a
protected method GetInstance() which has the same function of
A.GetInstance() in class E.   Remove the Method  A.GetInstance().
3 Add a static member 'B e ' withe the default access right in Class
B, construct 'e'in the static block of B as 'E':
          static{ e = new E; }

In this design B,C and D can invoke B.e.GetInstance() which is
E.GetInstance(), any other classes that is not in package XX.ZZ (and
also not in package XX.ZZ.GG) can't invoke the E.GetInstance().

Is my design OK ?
Andreas Leitgeb - 24 Jan 2008 12:05 GMT
> 1 Add a protect method GetInstance() in Class B;
> 2 Add a class E which is extends from B in package XX.ZZ.GG. Create a
[quoted text clipped - 3 lines]
> B, construct 'e'in the static block of B as 'E':
>            static{ e = new E; }

I'm not sure if I remember all involved classes correctly:
xx.zz.gg.B  is the one you want only accessible from
             classes in package xx.zz, which is principially
         not possible to guarantee from JLS point fo view.

So, you create a class
xx.zz.E which derives from B, and thus has also available
   all of B's protected functionality.

However, anyone else could create yet another derivative of B,
as hostile.mypackage.MyE, using the same mechanism as your E does,
to still access xx.zz.gg.B

> Is my design OK ?
It's quite complicated for hardly any gain.

Java's protection scheme *cannot* discriminate between two
packages, when both are different from the current one.
Whatever you can do from classes of package xx.zz to access
classes in xx.zz.gg,  you can always do the same from any
unrelated package aa.bb.cc, as well.

There are exactly these possibilities:
 - use reflection or exception-stacktraces at runtime to
      determine calling class (quite complicated, if you're
      stuck in 1.3, and still some overhead even with 1.4's
      new methods for easier stack-inspection.
 - put all the relevant classes in one package.  Or add a
      class C to package xx.zz.gg that will wrap B's methods
      such, that no misuse can occur when calling through C.
      Then you can give all B's methods default-access.

Maybe we can help more, if you tell us, who/what exactly you
want to protect your class B from.
E.g. against crackers? Against accidental inappropriate use
 from other parts of your own project?
Andreas Leitgeb - 24 Jan 2008 14:01 GMT
> There are exactly these possibilities:
>   - use reflection or exception-stacktraces at runtime to
>        determine calling class (quite complicated, if you're
>        stuck in 1.3, and still some overhead even with 1.4's
>        new methods for easier stack-inspection.

Based on Thomas Schodt's posting, the SecurityManager appears
to make a nicer variant of this strategy, but is still only
doing runtime-checking.

>   - put all the relevant classes in one package.  Or add a
>        class C to package xx.zz.gg that will wrap B's methods
>        such, that no misuse can occur when calling through C.
>        Then you can give all B's methods default-access.

That would allow compiletime checking.
Jebel - 25 Jan 2008 04:24 GMT
> >   - use reflection or exception-stacktraces at runtime to
> >        determine calling class (quite complicated, if you're
[quoted text clipped - 4 lines]
> to make a nicer variant of this strategy, but is still only
> doing runtime-checking.

I think homas Schodt's design is much better than mine, simple and
effective. But I want to know that if I invoke A.GetInstance() very
frequently, id the SecurityManager .getClassContext() going to take
much time?

-------------------------------------------------------------------------------------------------

> >   - put all the relevant classes in one package.  Or add a
> >        class C to package xx.zz.gg that will wrap B's methods
> >        such, that no misuse can occur when calling through C.
> >        Then you can give all B's methods default-access.
>
> That would allow compiletime checking.

I not understand how to do this. How can I "wrap" B's methods ?
Would you please provide some code as a example?

Thanks a lot.
Jebel
Andreas Leitgeb - 25 Jan 2008 11:58 GMT
> I not understand how to do this. How can I "wrap" B's methods ?
> Would you please provide some code as a example?

It was based on a wrong understanding on my side.  Sorry, but
I think it doesn't apply, anyway.

The point was about your class in xx.zz.gg  which you could
give a such limited interface, that noone could do anything
harmful with it, even if the wrong "user" tries...

The wrapping was just meant as a way to restrict the interface:
e.g.:
package xx.zz.gg;
class B {
  // lots of public methods, some of which are potentially dangerous
  public void foo() { ... }
  public void bar() { ... }
  public void snafu() { ... }
  ...
}
and:
package xx.zz.gg;
class BWrapper {
  B wrappedB;
  BWrapper(B b) { wrappedB=b; }
  private B getB() { return wrappedB; }
  // just the really important methods:
  public void foo() { do some checks, and then: getB().foo(); }
}  
After that, you can give all the methods of B default-access,
and no one else can use anything than foo() on B, and only through
your class BWrapper (unless they find a way to sneak code into
xx.zz or xx.zz.gg bypassing your classloader, or patching their
JVM).

Also, I don't yet understand what big evil would be unleashed by
letting people just use your  xx.zz.gg.B  as they feel like.
Jebel - 26 Jan 2008 05:22 GMT
On Jan 25, 7:58 pm, Andreas Leitgeb <a...@gamma.logic.tuwien.ac.at>
wrote:
> > I not understand how to do this. How can I "wrap" B's methods ?
> > Would you please provide some code as a example?
[quoted text clipped - 33 lines]
> Also, I don't yet understand what big evil would be unleashed by
> letting people just use your  xx.zz.gg.B  as they feel like.

Thank you Andreas.You have teach me much, and now I understand what is
the ' wrap ' . :-)
Thank you very much.
Jebel - 24 Jan 2008 14:41 GMT
> I'm not sure if I remember all involved classes correctly:
>  xx.zz.gg.B  is the one you want only accessible from
[quoted text clipped - 33 lines]
> E.g. against crackers? Against accidental inappropriate use
>   from other parts of your own project?

There is some thing that I didn't say clearly. I am designing a
platform and use some source(the package xx.zz) of another company, so
I can't move my source(the package xx.zz.gg) into the package xx.zz.
I can prevent the applications that use my source as platform to
create the package xx.zz from the classloader( the applications must
use the classloader that offered from me). And the class B will know
what is the name of my package and class. So I think applications
can't overrides my class E.
I want to prevent that if My design is betrayed, the applications also
can't disturb the behavior of package xx.zz.

And I am not very understand how to do this:

>   - put all the relevant classes in one package.  Or add a
>        class C to package xx.zz.gg that will wrap B's methods
>        such, that no misuse can occur when calling through C.
>        Then you can give all B's methods default-access.

Thank you very much.
Jebel
Roedy Green - 24 Jan 2008 08:57 GMT
>There is a class A in package XX.ZZ.GG , and A has a static method
>A.GetInstance(). There are 3 classes B, C, D in package XX.ZZ .
>How can I make the A.GetInstance() only can be invoked by the B, C and
>D.

Please follow the caps conventions. See
http://mindprod.com/jgloss/codingconventions.html

Your question translated then becomes:

>There is a class A in package xx.zz.gg, and A has a static method
>A.getInstance(). There are 3 classes B, C, D in package xx.zz .
>How can I make A.getInstance()so that it can only be invoked from
>classes B, C and D.

You can't. To do that classes A, B, C and D would have to be in the
same package, and getInstance would need default package scope.  You
could still invoke it from class A.

Note that, as far as Java is concerned, package xx.zz.gg and package
xx.zz are TOTALLY unrelated.  

see http://mindprod.com/jgloss/package.html
Signature

Roedy Green, Canadian Mind Products
The Java Glossary, http://mindprod.com

Jebel - 24 Jan 2008 09:54 GMT
On Jan 24, 4:57 pm, Roedy Green <see_webs...@mindprod.com.invalid>
wrote:
> On Mon, 21 Jan 2008 20:01:50 -0800 (PST), Jebel.S...@gmail.com wrote,
> quoted or indirectly quoted someone who said :
[quoted text clipped - 24 lines]
> Roedy Green, Canadian Mind Products
> The Java Glossary,http://mindprod.com

I know that "package xx.zz.gg and package xx.zz are TOTALLY unrelated
".The names of the two packages are no meaning for my problem.

 The classes A and E are in the package XX.ZZ.GG; and the classes B,
C and D are in the package XX.ZZ.
 The class E extends from class B.

 When the class C wants to invoke the E.GetInstance()(has the same
function of the previous A.GetInstance) it invokes B.e.GetInstance().

               package XX.ZZ;
               import  XX.ZZ.GG.A;
               public class C
               {
                   public void Func()
                   {
                        ... ...
                        A a = B.e.GetInstanc();
                        ... ...

                   }

               }

 The 'e' is a static member of class B, and 'e' is declared as B but
construct as E:

               package XX.ZZ;
               import  XX.ZZ.GG.E;
               import  XX.ZZ.GG.A;
               public class B
               {
                  static B e;

                  static{
                          e = new E;
                        }
                   protect A GetInstance(){ return null;}

                   ... ...
               }

 And the class E and class A are in the same package, E can do some
thing in its method GetInstance with A.
               package XX.ZZ.GG;
               import  XX.ZZ.B;
               final public class C extends B
               {
                   private static A onlyOne;
                   protect A GetInstance()
                   {
                        if(onlyOne == NULL){ onlyOne = new A;}
                        return onlyOne;
                    }
               }

 Class A :
               package XX.ZZ.GG;
               public class A
               {
                   // the access right of constructer of A is
default( the class in the same package can access)
                   A(){... ...}

                   ... ...
               }

 That is all.
Roedy Green - 24 Jan 2008 11:24 GMT
>     package XX.ZZ;

please don't do that. see
http://mindprod.com/jgloss/codingconventions.html
Signature

Roedy Green, Canadian Mind Products
The Java Glossary, http://mindprod.com

Lew - 24 Jan 2008 14:34 GMT
>>     package XX.ZZ;
>
> please don't do that. see
> http://mindprod.com/jgloss/codingconventions.html

Please note that ignoring good advice, especially from one such as Roedy who
really goes out of his way to be helpful, is risky.  You send a message that
you aren't really interested in good advice, thus lowering the expected value
of advice that you will receive.  Quoting that advice, then disregarding,
gives the no doubt accidental impression that you are evincing deliberate
disrespect.  I'm sure that you did not mean that, of course.

There's good reason for the coding conventions, particular where upper- and
lower-case names are concerned.  These conventions facilitate discourse about
Java programs.  Discourse about Java programs is the whole point of the
clj.programmer newsgroup.  There is a tolerance for variation from some parts
of the convention, formalized in 1999, but only to a point.  Indentation, for
example, has two major variants with permissible indentation sizes that can
vary in a narrow range.  However, the case conventions are pretty solid and
should not be ignored.

Java from the beginning has been a "literate programming" language -
information about the program is embedded in the source code for the program.
 Javadocs are one aspect of that.  Annotations are another.  The naming
conventions stress the use of names out of the domain of discourse - the
logical model for the program, not out of the implementation.  Thus
"WidgetExtractor" tells us by the initial upper-case letter that this is a
class name for something that models a widget extractor.  No need to embed the
redundant "Class" in a name like "WidgetExtractorClass".  The identifier
"widgetExtractor" in this context now tells us that we see an instance of that
class.  "widgetExtractor()" jars the senses, because it's a noun phrase for a
method name; "widgetExtract()" would be more comfortable.  With little if any
cognitive strain one can infer many things about the logic and the domain
model from a source code artifact without interrupting the flow of reviewing
it, if these conventions are rigorously followed.

So please, for both engineering and social reasons, use lower-case identifiers
for your package names.

Signature

Lew

Thomas Schodt - 24 Jan 2008 13:47 GMT
> There is a class A in package xx.zz.gg , and A has a static method
> A.getInstance(). There are 3 classes B, C, D in package xx.zz
> How can I make the A.getInstance() only can be invoked by the B, C and D

class A {
  private A() {};
  private static final Set allowed = new HashSet() {{
    add("xx.zz.B");
    add("xx.zz.C");
    add("xx.zz.D");
  }};
  static A a = null;
  static A getInstance() {
    Class[] ca = new SecurityManager() {
        protected Class[] getClassContext() {
            return super.getClassContext();
        }
    }.getClassContext();
    // ca[0] is the anonymous security manager
    // ca[1] is this class ("A")
    // ca[2] is the calling class
    if (!allowed.contains(ca[2].getName())) {
      throw new InstantiationError("Not allowed from "+ca[2]);
    }
    if (a==null) { a = new A(); }
    return a;
  }
}
Lew - 24 Jan 2008 14:46 GMT
>> There is a class A in package xx.zz.gg , and A has a static method
>> A.getInstance(). There are 3 classes B, C, D in package xx.zz
[quoted text clipped - 24 lines]
>   }
> }

That's a great pattern.  Take it a step further and store a
Map <String, Class <? extends Allowed>>
or a Map <AllowedEnum, Class <? extends Allowed>>
where 'Allowed' is a supertype for the classes that are allowed.  The 'String'
or 'AllowedEnum' enum identify the particular implementing class for each case
you want to permit.

For that matter, you could craft an 'AllowedEnum' where each enum instance's
behavior does what you want - that could well be your optimal solution in that
it gives you compile-time safety on the behaviors, not merely run-time checks.
 From a maintenance standpoint, such an enum collects verification of an
action's legality and its activity into a single class, binding them at
compile time, making life easier.

The downside to the enum implementation is that you have to recompile the
world to extend the behaviors.  If runtime configurability is what you need,
then you need a runtime technique such as the ServiceProvider pattern.

Signature

Lew

Roedy Green - 24 Jan 2008 20:59 GMT
On Thu, 24 Jan 2008 13:47:14 +0000, Thomas Schodt
<spamtrap0607@xenoc.demon.co.uk> wrote, quoted or indirectly quoted
someone who said :

It seems to me you would have to make getClassContext public.  Is it
accessible just as protected?  The original was already protected.

// Determining the calling class.
// ca[0] is the anonymous security manager
// ca[1] is this class
// ca[2] is the calling class
Class[] ca = new SecurityManager()
  {
  // convert from protected to public to make the method accessible.
  public Class[] getClassContext()
     {
     return super.getClassContext();
     }
  }.getClassContext();

Signature

Roedy Green, Canadian Mind Products
The Java Glossary, http://mindprod.com

Jebel - 26 Jan 2008 05:09 GMT
On Jan 25, 4:59 am, Roedy Green <see_webs...@mindprod.com.invalid>
wrote:
> On Thu, 24 Jan 2008 13:47:14 +0000, Thomas Schodt
> <spamtrap0...@xenoc.demon.co.uk> wrote, quoted or indirectly quoted
[quoted text clipped - 19 lines]
> Roedy Green, Canadian Mind Products
> The Java Glossary,http://mindprod.com

No, it's needn't. A class can invoke the methods with protected-access
of the inner classes.
Stefan Ram - 24 Jan 2008 15:24 GMT
>How can I make the A.GetInstance() only can be invoked by the B

 Any static measure is insufficient, because new classes
 can be generated and loaded at run-time. Such classes would
 not have been inspected by a static measure.

 Therefore, the measure must be dynamic. The answers I am aware
 of have implied that »A.GetInstance()« will somehow check its
 caller. Such answers do not actually address how to /prevent/
 the invocation, because at the time when »A.GetInstance()«
 checks its caller it already /has been/ invoked, so it is too
 late to prevent it. The question was to prevent this, not to
 detect and report it, once it has happend.

 Therefore, it might not be possible to do this at all.

 One could use a patched JVM to do this.

 However, there might be multiple »B« classes (one for each
 class loader). One also needs to specify which of them should
 be allowed to call »A.GetInstance()«. For this, one needs
 to identify the class loaders involved.


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.